diff options
author | Tejun Heo <tj@kernel.org> | 2010-12-12 10:45:14 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2010-12-12 10:45:14 -0500 |
commit | 781ba4567698be9db7ca94d827c4b38d8583c168 (patch) | |
tree | a1083df1054b48078e311fc80d6e135201bc10c1 /drivers/net/wimax | |
parent | fe8998c5e3b173f3d5c450bbde6173e7fbe5158d (diff) |
i2400m: drop i2400m_schedule_work()
i2400m implements dynamic work allocation and queueing mechanism in
i2400_schedule_work(); however, this is only used for reset and
recovery which can be served equally well with preallocated per device
works.
Replace i2400m_schedule_work() with two work structs in struct i2400m.
These works are explicitly canceled when the device is released making
calls to flush_scheduled_work(), which is being deprecated,
unnecessary.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
Cc: linux-wimax@intel.com
Cc: netdev@vger.kernel.org
Diffstat (limited to 'drivers/net/wimax')
-rw-r--r-- | drivers/net/wimax/i2400m/driver.c | 96 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/i2400m.h | 19 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/sdio.c | 1 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/usb.c | 1 |
4 files changed, 21 insertions, 96 deletions
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c index cdedab46ba21..f0603327aafa 100644 --- a/drivers/net/wimax/i2400m/driver.c +++ b/drivers/net/wimax/i2400m/driver.c | |||
@@ -92,54 +92,6 @@ MODULE_PARM_DESC(barkers, | |||
92 | "signal; values are appended to a list--setting one value " | 92 | "signal; values are appended to a list--setting one value " |
93 | "as zero cleans the existing list and starts a new one."); | 93 | "as zero cleans the existing list and starts a new one."); |
94 | 94 | ||
95 | static | ||
96 | struct i2400m_work *__i2400m_work_setup( | ||
97 | struct i2400m *i2400m, void (*fn)(struct work_struct *), | ||
98 | gfp_t gfp_flags, const void *pl, size_t pl_size) | ||
99 | { | ||
100 | struct i2400m_work *iw; | ||
101 | |||
102 | iw = kzalloc(sizeof(*iw) + pl_size, gfp_flags); | ||
103 | if (iw == NULL) | ||
104 | return NULL; | ||
105 | iw->i2400m = i2400m_get(i2400m); | ||
106 | iw->pl_size = pl_size; | ||
107 | memcpy(iw->pl, pl, pl_size); | ||
108 | INIT_WORK(&iw->ws, fn); | ||
109 | return iw; | ||
110 | } | ||
111 | |||
112 | |||
113 | /* | ||
114 | * Schedule i2400m's specific work on the system's queue. | ||
115 | * | ||
116 | * Used for a few cases where we really need it; otherwise, identical | ||
117 | * to i2400m_queue_work(). | ||
118 | * | ||
119 | * Returns < 0 errno code on error, 1 if ok. | ||
120 | * | ||
121 | * If it returns zero, something really bad happened, as it means the | ||
122 | * works struct was already queued, but we have just allocated it, so | ||
123 | * it should not happen. | ||
124 | */ | ||
125 | static int i2400m_schedule_work(struct i2400m *i2400m, | ||
126 | void (*fn)(struct work_struct *), gfp_t gfp_flags, | ||
127 | const void *pl, size_t pl_size) | ||
128 | { | ||
129 | int result; | ||
130 | struct i2400m_work *iw; | ||
131 | |||
132 | result = -ENOMEM; | ||
133 | iw = __i2400m_work_setup(i2400m, fn, gfp_flags, pl, pl_size); | ||
134 | if (iw != NULL) { | ||
135 | result = schedule_work(&iw->ws); | ||
136 | if (WARN_ON(result == 0)) | ||
137 | result = -ENXIO; | ||
138 | } | ||
139 | return result; | ||
140 | } | ||
141 | |||
142 | |||
143 | /* | 95 | /* |
144 | * WiMAX stack operation: relay a message from user space | 96 | * WiMAX stack operation: relay a message from user space |
145 | * | 97 | * |
@@ -648,17 +600,11 @@ EXPORT_SYMBOL_GPL(i2400m_post_reset); | |||
648 | static | 600 | static |
649 | void __i2400m_dev_reset_handle(struct work_struct *ws) | 601 | void __i2400m_dev_reset_handle(struct work_struct *ws) |
650 | { | 602 | { |
651 | int result; | 603 | struct i2400m *i2400m = container_of(ws, struct i2400m, reset_ws); |
652 | struct i2400m_work *iw = container_of(ws, struct i2400m_work, ws); | 604 | const char *reason = i2400m->reset_reason; |
653 | const char *reason; | ||
654 | struct i2400m *i2400m = iw->i2400m; | ||
655 | struct device *dev = i2400m_dev(i2400m); | 605 | struct device *dev = i2400m_dev(i2400m); |
656 | struct i2400m_reset_ctx *ctx = i2400m->reset_ctx; | 606 | struct i2400m_reset_ctx *ctx = i2400m->reset_ctx; |
657 | 607 | int result; | |
658 | if (WARN_ON(iw->pl_size != sizeof(reason))) | ||
659 | reason = "SW BUG: reason n/a"; | ||
660 | else | ||
661 | memcpy(&reason, iw->pl, sizeof(reason)); | ||
662 | 608 | ||
663 | d_fnstart(3, dev, "(ws %p i2400m %p reason %s)\n", ws, i2400m, reason); | 609 | d_fnstart(3, dev, "(ws %p i2400m %p reason %s)\n", ws, i2400m, reason); |
664 | 610 | ||
@@ -733,8 +679,6 @@ void __i2400m_dev_reset_handle(struct work_struct *ws) | |||
733 | } | 679 | } |
734 | } | 680 | } |
735 | out: | 681 | out: |
736 | i2400m_put(i2400m); | ||
737 | kfree(iw); | ||
738 | d_fnend(3, dev, "(ws %p i2400m %p reason %s) = void\n", | 682 | d_fnend(3, dev, "(ws %p i2400m %p reason %s) = void\n", |
739 | ws, i2400m, reason); | 683 | ws, i2400m, reason); |
740 | } | 684 | } |
@@ -754,8 +698,8 @@ out: | |||
754 | */ | 698 | */ |
755 | int i2400m_dev_reset_handle(struct i2400m *i2400m, const char *reason) | 699 | int i2400m_dev_reset_handle(struct i2400m *i2400m, const char *reason) |
756 | { | 700 | { |
757 | return i2400m_schedule_work(i2400m, __i2400m_dev_reset_handle, | 701 | i2400m->reset_reason = reason; |
758 | GFP_ATOMIC, &reason, sizeof(reason)); | 702 | return schedule_work(&i2400m->reset_ws); |
759 | } | 703 | } |
760 | EXPORT_SYMBOL_GPL(i2400m_dev_reset_handle); | 704 | EXPORT_SYMBOL_GPL(i2400m_dev_reset_handle); |
761 | 705 | ||
@@ -768,14 +712,9 @@ EXPORT_SYMBOL_GPL(i2400m_dev_reset_handle); | |||
768 | static | 712 | static |
769 | void __i2400m_error_recovery(struct work_struct *ws) | 713 | void __i2400m_error_recovery(struct work_struct *ws) |
770 | { | 714 | { |
771 | struct i2400m_work *iw = container_of(ws, struct i2400m_work, ws); | 715 | struct i2400m *i2400m = container_of(ws, struct i2400m, recovery_ws); |
772 | struct i2400m *i2400m = iw->i2400m; | ||
773 | 716 | ||
774 | i2400m_reset(i2400m, I2400M_RT_BUS); | 717 | i2400m_reset(i2400m, I2400M_RT_BUS); |
775 | |||
776 | i2400m_put(i2400m); | ||
777 | kfree(iw); | ||
778 | return; | ||
779 | } | 718 | } |
780 | 719 | ||
781 | /* | 720 | /* |
@@ -805,18 +744,10 @@ void __i2400m_error_recovery(struct work_struct *ws) | |||
805 | */ | 744 | */ |
806 | void i2400m_error_recovery(struct i2400m *i2400m) | 745 | void i2400m_error_recovery(struct i2400m *i2400m) |
807 | { | 746 | { |
808 | struct device *dev = i2400m_dev(i2400m); | 747 | if (atomic_add_return(1, &i2400m->error_recovery) == 1) |
809 | 748 | schedule_work(&i2400m->recovery_ws); | |
810 | if (atomic_add_return(1, &i2400m->error_recovery) == 1) { | 749 | else |
811 | if (i2400m_schedule_work(i2400m, __i2400m_error_recovery, | ||
812 | GFP_ATOMIC, NULL, 0) < 0) { | ||
813 | dev_err(dev, "run out of memory for " | ||
814 | "scheduling an error recovery ?\n"); | ||
815 | atomic_dec(&i2400m->error_recovery); | ||
816 | } | ||
817 | } else | ||
818 | atomic_dec(&i2400m->error_recovery); | 750 | atomic_dec(&i2400m->error_recovery); |
819 | return; | ||
820 | } | 751 | } |
821 | EXPORT_SYMBOL_GPL(i2400m_error_recovery); | 752 | EXPORT_SYMBOL_GPL(i2400m_error_recovery); |
822 | 753 | ||
@@ -886,6 +817,10 @@ void i2400m_init(struct i2400m *i2400m) | |||
886 | 817 | ||
887 | mutex_init(&i2400m->init_mutex); | 818 | mutex_init(&i2400m->init_mutex); |
888 | /* wake_tx_ws is initialized in i2400m_tx_setup() */ | 819 | /* wake_tx_ws is initialized in i2400m_tx_setup() */ |
820 | |||
821 | INIT_WORK(&i2400m->reset_ws, __i2400m_dev_reset_handle); | ||
822 | INIT_WORK(&i2400m->recovery_ws, __i2400m_error_recovery); | ||
823 | |||
889 | atomic_set(&i2400m->bus_reset_retries, 0); | 824 | atomic_set(&i2400m->bus_reset_retries, 0); |
890 | 825 | ||
891 | i2400m->alive = 0; | 826 | i2400m->alive = 0; |
@@ -1040,6 +975,9 @@ void i2400m_release(struct i2400m *i2400m) | |||
1040 | 975 | ||
1041 | i2400m_dev_stop(i2400m); | 976 | i2400m_dev_stop(i2400m); |
1042 | 977 | ||
978 | cancel_work_sync(&i2400m->reset_ws); | ||
979 | cancel_work_sync(&i2400m->recovery_ws); | ||
980 | |||
1043 | i2400m_debugfs_rm(i2400m); | 981 | i2400m_debugfs_rm(i2400m); |
1044 | sysfs_remove_group(&i2400m->wimax_dev.net_dev->dev.kobj, | 982 | sysfs_remove_group(&i2400m->wimax_dev.net_dev->dev.kobj, |
1045 | &i2400m_dev_attr_group); | 983 | &i2400m_dev_attr_group); |
@@ -1083,8 +1021,6 @@ module_init(i2400m_driver_init); | |||
1083 | static | 1021 | static |
1084 | void __exit i2400m_driver_exit(void) | 1022 | void __exit i2400m_driver_exit(void) |
1085 | { | 1023 | { |
1086 | /* for scheds i2400m_dev_reset_handle() */ | ||
1087 | flush_scheduled_work(); | ||
1088 | i2400m_barker_db_exit(); | 1024 | i2400m_barker_db_exit(); |
1089 | } | 1025 | } |
1090 | module_exit(i2400m_driver_exit); | 1026 | module_exit(i2400m_driver_exit); |
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h index 59ac7705e76e..17ecaa41a807 100644 --- a/drivers/net/wimax/i2400m/i2400m.h +++ b/drivers/net/wimax/i2400m/i2400m.h | |||
@@ -632,6 +632,11 @@ struct i2400m { | |||
632 | struct work_struct wake_tx_ws; | 632 | struct work_struct wake_tx_ws; |
633 | struct sk_buff *wake_tx_skb; | 633 | struct sk_buff *wake_tx_skb; |
634 | 634 | ||
635 | struct work_struct reset_ws; | ||
636 | const char *reset_reason; | ||
637 | |||
638 | struct work_struct recovery_ws; | ||
639 | |||
635 | struct dentry *debugfs_dentry; | 640 | struct dentry *debugfs_dentry; |
636 | const char *fw_name; /* name of the current firmware image */ | 641 | const char *fw_name; /* name of the current firmware image */ |
637 | unsigned long fw_version; /* version of the firmware interface */ | 642 | unsigned long fw_version; /* version of the firmware interface */ |
@@ -896,20 +901,6 @@ struct device *i2400m_dev(struct i2400m *i2400m) | |||
896 | return i2400m->wimax_dev.net_dev->dev.parent; | 901 | return i2400m->wimax_dev.net_dev->dev.parent; |
897 | } | 902 | } |
898 | 903 | ||
899 | /* | ||
900 | * Helper for scheduling simple work functions | ||
901 | * | ||
902 | * This struct can get any kind of payload attached (normally in the | ||
903 | * form of a struct where you pack the stuff you want to pass to the | ||
904 | * _work function). | ||
905 | */ | ||
906 | struct i2400m_work { | ||
907 | struct work_struct ws; | ||
908 | struct i2400m *i2400m; | ||
909 | size_t pl_size; | ||
910 | u8 pl[0]; | ||
911 | }; | ||
912 | |||
913 | extern int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *, | 904 | extern int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *, |
914 | char *, size_t); | 905 | char *, size_t); |
915 | extern int i2400m_msg_size_check(struct i2400m *, | 906 | extern int i2400m_msg_size_check(struct i2400m *, |
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c index 9bfc26e1bc6b..be428cae28d8 100644 --- a/drivers/net/wimax/i2400m/sdio.c +++ b/drivers/net/wimax/i2400m/sdio.c | |||
@@ -590,7 +590,6 @@ module_init(i2400ms_driver_init); | |||
590 | static | 590 | static |
591 | void __exit i2400ms_driver_exit(void) | 591 | void __exit i2400ms_driver_exit(void) |
592 | { | 592 | { |
593 | flush_scheduled_work(); /* for the stuff we schedule */ | ||
594 | sdio_unregister_driver(&i2400m_sdio_driver); | 593 | sdio_unregister_driver(&i2400m_sdio_driver); |
595 | } | 594 | } |
596 | module_exit(i2400ms_driver_exit); | 595 | module_exit(i2400ms_driver_exit); |
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index d3365ac85dde..10e3ab352175 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c | |||
@@ -780,7 +780,6 @@ module_init(i2400mu_driver_init); | |||
780 | static | 780 | static |
781 | void __exit i2400mu_driver_exit(void) | 781 | void __exit i2400mu_driver_exit(void) |
782 | { | 782 | { |
783 | flush_scheduled_work(); /* for the stuff we schedule from sysfs.c */ | ||
784 | usb_deregister(&i2400mu_driver); | 783 | usb_deregister(&i2400mu_driver); |
785 | } | 784 | } |
786 | module_exit(i2400mu_driver_exit); | 785 | module_exit(i2400mu_driver_exit); |