diff options
Diffstat (limited to 'drivers/char/hvcs.c')
-rw-r--r-- | drivers/char/hvcs.c | 78 |
1 files changed, 25 insertions, 53 deletions
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 69d8866de783..fd7559084b82 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c | |||
@@ -57,11 +57,7 @@ | |||
57 | * rescanning partner information upon a user's request. | 57 | * rescanning partner information upon a user's request. |
58 | * | 58 | * |
59 | * Each vty-server, prior to being exposed to this driver is reference counted | 59 | * Each vty-server, prior to being exposed to this driver is reference counted |
60 | * using the 2.6 Linux kernel kobject construct. This kobject is also used by | 60 | * using the 2.6 Linux kernel kref construct. |
61 | * the vio bus to provide a vio device sysfs entry that this driver attaches | ||
62 | * device specific attributes to, including partner information. The vio bus | ||
63 | * framework also provides a sysfs entry for each vio driver. The hvcs driver | ||
64 | * provides driver attributes in this entry. | ||
65 | * | 61 | * |
66 | * For direction on installation and usage of this driver please reference | 62 | * For direction on installation and usage of this driver please reference |
67 | * Documentation/powerpc/hvcs.txt. | 63 | * Documentation/powerpc/hvcs.txt. |
@@ -71,7 +67,7 @@ | |||
71 | #include <linux/init.h> | 67 | #include <linux/init.h> |
72 | #include <linux/interrupt.h> | 68 | #include <linux/interrupt.h> |
73 | #include <linux/kernel.h> | 69 | #include <linux/kernel.h> |
74 | #include <linux/kobject.h> | 70 | #include <linux/kref.h> |
75 | #include <linux/kthread.h> | 71 | #include <linux/kthread.h> |
76 | #include <linux/list.h> | 72 | #include <linux/list.h> |
77 | #include <linux/major.h> | 73 | #include <linux/major.h> |
@@ -293,12 +289,12 @@ struct hvcs_struct { | |||
293 | int chars_in_buffer; | 289 | int chars_in_buffer; |
294 | 290 | ||
295 | /* | 291 | /* |
296 | * Any variable below the kobject is valid before a tty is connected and | 292 | * Any variable below the kref is valid before a tty is connected and |
297 | * stays valid after the tty is disconnected. These shouldn't be | 293 | * stays valid after the tty is disconnected. These shouldn't be |
298 | * whacked until the koject refcount reaches zero though some entries | 294 | * whacked until the koject refcount reaches zero though some entries |
299 | * may be changed via sysfs initiatives. | 295 | * may be changed via sysfs initiatives. |
300 | */ | 296 | */ |
301 | struct kobject kobj; /* ref count & hvcs_struct lifetime */ | 297 | struct kref kref; /* ref count & hvcs_struct lifetime */ |
302 | int connected; /* is the vty-server currently connected to a vty? */ | 298 | int connected; /* is the vty-server currently connected to a vty? */ |
303 | uint32_t p_unit_address; /* partner unit address */ | 299 | uint32_t p_unit_address; /* partner unit address */ |
304 | uint32_t p_partition_ID; /* partner partition ID */ | 300 | uint32_t p_partition_ID; /* partner partition ID */ |
@@ -307,8 +303,8 @@ struct hvcs_struct { | |||
307 | struct vio_dev *vdev; | 303 | struct vio_dev *vdev; |
308 | }; | 304 | }; |
309 | 305 | ||
310 | /* Required to back map a kobject to its containing object */ | 306 | /* Required to back map a kref to its containing object */ |
311 | #define from_kobj(kobj) container_of(kobj, struct hvcs_struct, kobj) | 307 | #define from_kref(k) container_of(k, struct hvcs_struct, kref) |
312 | 308 | ||
313 | static struct list_head hvcs_structs = LIST_HEAD_INIT(hvcs_structs); | 309 | static struct list_head hvcs_structs = LIST_HEAD_INIT(hvcs_structs); |
314 | static DEFINE_SPINLOCK(hvcs_structs_lock); | 310 | static DEFINE_SPINLOCK(hvcs_structs_lock); |
@@ -334,7 +330,6 @@ static void hvcs_partner_free(struct hvcs_struct *hvcsd); | |||
334 | static int hvcs_enable_device(struct hvcs_struct *hvcsd, | 330 | static int hvcs_enable_device(struct hvcs_struct *hvcsd, |
335 | uint32_t unit_address, unsigned int irq, struct vio_dev *dev); | 331 | uint32_t unit_address, unsigned int irq, struct vio_dev *dev); |
336 | 332 | ||
337 | static void destroy_hvcs_struct(struct kobject *kobj); | ||
338 | static int hvcs_open(struct tty_struct *tty, struct file *filp); | 333 | static int hvcs_open(struct tty_struct *tty, struct file *filp); |
339 | static void hvcs_close(struct tty_struct *tty, struct file *filp); | 334 | static void hvcs_close(struct tty_struct *tty, struct file *filp); |
340 | static void hvcs_hangup(struct tty_struct * tty); | 335 | static void hvcs_hangup(struct tty_struct * tty); |
@@ -703,10 +698,10 @@ static void hvcs_return_index(int index) | |||
703 | hvcs_index_list[index] = -1; | 698 | hvcs_index_list[index] = -1; |
704 | } | 699 | } |
705 | 700 | ||
706 | /* callback when the kboject ref count reaches zero */ | 701 | /* callback when the kref ref count reaches zero */ |
707 | static void destroy_hvcs_struct(struct kobject *kobj) | 702 | static void destroy_hvcs_struct(struct kref *kref) |
708 | { | 703 | { |
709 | struct hvcs_struct *hvcsd = from_kobj(kobj); | 704 | struct hvcs_struct *hvcsd = from_kref(kref); |
710 | struct vio_dev *vdev; | 705 | struct vio_dev *vdev; |
711 | unsigned long flags; | 706 | unsigned long flags; |
712 | 707 | ||
@@ -743,10 +738,6 @@ static void destroy_hvcs_struct(struct kobject *kobj) | |||
743 | kfree(hvcsd); | 738 | kfree(hvcsd); |
744 | } | 739 | } |
745 | 740 | ||
746 | static struct kobj_type hvcs_kobj_type = { | ||
747 | .release = destroy_hvcs_struct, | ||
748 | }; | ||
749 | |||
750 | static int hvcs_get_index(void) | 741 | static int hvcs_get_index(void) |
751 | { | 742 | { |
752 | int i; | 743 | int i; |
@@ -791,9 +782,7 @@ static int __devinit hvcs_probe( | |||
791 | 782 | ||
792 | spin_lock_init(&hvcsd->lock); | 783 | spin_lock_init(&hvcsd->lock); |
793 | /* Automatically incs the refcount the first time */ | 784 | /* Automatically incs the refcount the first time */ |
794 | kobject_init(&hvcsd->kobj); | 785 | kref_init(&hvcsd->kref); |
795 | /* Set up the callback for terminating the hvcs_struct's life */ | ||
796 | hvcsd->kobj.ktype = &hvcs_kobj_type; | ||
797 | 786 | ||
798 | hvcsd->vdev = dev; | 787 | hvcsd->vdev = dev; |
799 | dev->dev.driver_data = hvcsd; | 788 | dev->dev.driver_data = hvcsd; |
@@ -844,7 +833,6 @@ static int __devexit hvcs_remove(struct vio_dev *dev) | |||
844 | { | 833 | { |
845 | struct hvcs_struct *hvcsd = dev->dev.driver_data; | 834 | struct hvcs_struct *hvcsd = dev->dev.driver_data; |
846 | unsigned long flags; | 835 | unsigned long flags; |
847 | struct kobject *kobjp; | ||
848 | struct tty_struct *tty; | 836 | struct tty_struct *tty; |
849 | 837 | ||
850 | if (!hvcsd) | 838 | if (!hvcsd) |
@@ -856,15 +844,13 @@ static int __devexit hvcs_remove(struct vio_dev *dev) | |||
856 | 844 | ||
857 | tty = hvcsd->tty; | 845 | tty = hvcsd->tty; |
858 | 846 | ||
859 | kobjp = &hvcsd->kobj; | ||
860 | |||
861 | spin_unlock_irqrestore(&hvcsd->lock, flags); | 847 | spin_unlock_irqrestore(&hvcsd->lock, flags); |
862 | 848 | ||
863 | /* | 849 | /* |
864 | * Let the last holder of this object cause it to be removed, which | 850 | * Let the last holder of this object cause it to be removed, which |
865 | * would probably be tty_hangup below. | 851 | * would probably be tty_hangup below. |
866 | */ | 852 | */ |
867 | kobject_put (kobjp); | 853 | kref_put(&hvcsd->kref, destroy_hvcs_struct); |
868 | 854 | ||
869 | /* | 855 | /* |
870 | * The hangup is a scheduled function which will auto chain call | 856 | * The hangup is a scheduled function which will auto chain call |
@@ -1086,7 +1072,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address, | |||
1086 | } | 1072 | } |
1087 | 1073 | ||
1088 | /* | 1074 | /* |
1089 | * This always increments the kobject ref count if the call is successful. | 1075 | * This always increments the kref ref count if the call is successful. |
1090 | * Please remember to dec when you are done with the instance. | 1076 | * Please remember to dec when you are done with the instance. |
1091 | * | 1077 | * |
1092 | * NOTICE: Do NOT hold either the hvcs_struct.lock or hvcs_structs_lock when | 1078 | * NOTICE: Do NOT hold either the hvcs_struct.lock or hvcs_structs_lock when |
@@ -1103,7 +1089,7 @@ static struct hvcs_struct *hvcs_get_by_index(int index) | |||
1103 | list_for_each_entry(hvcsd, &hvcs_structs, next) { | 1089 | list_for_each_entry(hvcsd, &hvcs_structs, next) { |
1104 | spin_lock_irqsave(&hvcsd->lock, flags); | 1090 | spin_lock_irqsave(&hvcsd->lock, flags); |
1105 | if (hvcsd->index == index) { | 1091 | if (hvcsd->index == index) { |
1106 | kobject_get(&hvcsd->kobj); | 1092 | kref_get(&hvcsd->kref); |
1107 | spin_unlock_irqrestore(&hvcsd->lock, flags); | 1093 | spin_unlock_irqrestore(&hvcsd->lock, flags); |
1108 | spin_unlock(&hvcs_structs_lock); | 1094 | spin_unlock(&hvcs_structs_lock); |
1109 | return hvcsd; | 1095 | return hvcsd; |
@@ -1129,14 +1115,13 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp) | |||
1129 | unsigned int irq; | 1115 | unsigned int irq; |
1130 | struct vio_dev *vdev; | 1116 | struct vio_dev *vdev; |
1131 | unsigned long unit_address; | 1117 | unsigned long unit_address; |
1132 | struct kobject *kobjp; | ||
1133 | 1118 | ||
1134 | if (tty->driver_data) | 1119 | if (tty->driver_data) |
1135 | goto fast_open; | 1120 | goto fast_open; |
1136 | 1121 | ||
1137 | /* | 1122 | /* |
1138 | * Is there a vty-server that shares the same index? | 1123 | * Is there a vty-server that shares the same index? |
1139 | * This function increments the kobject index. | 1124 | * This function increments the kref index. |
1140 | */ | 1125 | */ |
1141 | if (!(hvcsd = hvcs_get_by_index(tty->index))) { | 1126 | if (!(hvcsd = hvcs_get_by_index(tty->index))) { |
1142 | printk(KERN_WARNING "HVCS: open failed, no device associated" | 1127 | printk(KERN_WARNING "HVCS: open failed, no device associated" |
@@ -1181,7 +1166,7 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp) | |||
1181 | * and will grab the spinlock and free the connection if it fails. | 1166 | * and will grab the spinlock and free the connection if it fails. |
1182 | */ | 1167 | */ |
1183 | if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) { | 1168 | if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) { |
1184 | kobject_put(&hvcsd->kobj); | 1169 | kref_put(&hvcsd->kref, destroy_hvcs_struct); |
1185 | printk(KERN_WARNING "HVCS: enable device failed.\n"); | 1170 | printk(KERN_WARNING "HVCS: enable device failed.\n"); |
1186 | return rc; | 1171 | return rc; |
1187 | } | 1172 | } |
@@ -1192,17 +1177,11 @@ fast_open: | |||
1192 | hvcsd = tty->driver_data; | 1177 | hvcsd = tty->driver_data; |
1193 | 1178 | ||
1194 | spin_lock_irqsave(&hvcsd->lock, flags); | 1179 | spin_lock_irqsave(&hvcsd->lock, flags); |
1195 | if (!kobject_get(&hvcsd->kobj)) { | 1180 | kref_get(&hvcsd->kref); |
1196 | spin_unlock_irqrestore(&hvcsd->lock, flags); | ||
1197 | printk(KERN_ERR "HVCS: Kobject of open" | ||
1198 | " hvcs doesn't exist.\n"); | ||
1199 | return -EFAULT; /* Is this the right return value? */ | ||
1200 | } | ||
1201 | |||
1202 | hvcsd->open_count++; | 1181 | hvcsd->open_count++; |
1203 | |||
1204 | hvcsd->todo_mask |= HVCS_SCHED_READ; | 1182 | hvcsd->todo_mask |= HVCS_SCHED_READ; |
1205 | spin_unlock_irqrestore(&hvcsd->lock, flags); | 1183 | spin_unlock_irqrestore(&hvcsd->lock, flags); |
1184 | |||
1206 | open_success: | 1185 | open_success: |
1207 | hvcs_kick(); | 1186 | hvcs_kick(); |
1208 | 1187 | ||
@@ -1212,9 +1191,8 @@ open_success: | |||
1212 | return 0; | 1191 | return 0; |
1213 | 1192 | ||
1214 | error_release: | 1193 | error_release: |
1215 | kobjp = &hvcsd->kobj; | ||
1216 | spin_unlock_irqrestore(&hvcsd->lock, flags); | 1194 | spin_unlock_irqrestore(&hvcsd->lock, flags); |
1217 | kobject_put(&hvcsd->kobj); | 1195 | kref_put(&hvcsd->kref, destroy_hvcs_struct); |
1218 | 1196 | ||
1219 | printk(KERN_WARNING "HVCS: partner connect failed.\n"); | 1197 | printk(KERN_WARNING "HVCS: partner connect failed.\n"); |
1220 | return retval; | 1198 | return retval; |
@@ -1224,7 +1202,6 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) | |||
1224 | { | 1202 | { |
1225 | struct hvcs_struct *hvcsd; | 1203 | struct hvcs_struct *hvcsd; |
1226 | unsigned long flags; | 1204 | unsigned long flags; |
1227 | struct kobject *kobjp; | ||
1228 | int irq = NO_IRQ; | 1205 | int irq = NO_IRQ; |
1229 | 1206 | ||
1230 | /* | 1207 | /* |
@@ -1245,7 +1222,6 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) | |||
1245 | hvcsd = tty->driver_data; | 1222 | hvcsd = tty->driver_data; |
1246 | 1223 | ||
1247 | spin_lock_irqsave(&hvcsd->lock, flags); | 1224 | spin_lock_irqsave(&hvcsd->lock, flags); |
1248 | kobjp = &hvcsd->kobj; | ||
1249 | if (--hvcsd->open_count == 0) { | 1225 | if (--hvcsd->open_count == 0) { |
1250 | 1226 | ||
1251 | vio_disable_interrupts(hvcsd->vdev); | 1227 | vio_disable_interrupts(hvcsd->vdev); |
@@ -1270,7 +1246,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) | |||
1270 | tty->driver_data = NULL; | 1246 | tty->driver_data = NULL; |
1271 | 1247 | ||
1272 | free_irq(irq, hvcsd); | 1248 | free_irq(irq, hvcsd); |
1273 | kobject_put(kobjp); | 1249 | kref_put(&hvcsd->kref, destroy_hvcs_struct); |
1274 | return; | 1250 | return; |
1275 | } else if (hvcsd->open_count < 0) { | 1251 | } else if (hvcsd->open_count < 0) { |
1276 | printk(KERN_ERR "HVCS: vty-server@%X open_count: %d" | 1252 | printk(KERN_ERR "HVCS: vty-server@%X open_count: %d" |
@@ -1279,7 +1255,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) | |||
1279 | } | 1255 | } |
1280 | 1256 | ||
1281 | spin_unlock_irqrestore(&hvcsd->lock, flags); | 1257 | spin_unlock_irqrestore(&hvcsd->lock, flags); |
1282 | kobject_put(kobjp); | 1258 | kref_put(&hvcsd->kref, destroy_hvcs_struct); |
1283 | } | 1259 | } |
1284 | 1260 | ||
1285 | static void hvcs_hangup(struct tty_struct * tty) | 1261 | static void hvcs_hangup(struct tty_struct * tty) |
@@ -1287,21 +1263,17 @@ static void hvcs_hangup(struct tty_struct * tty) | |||
1287 | struct hvcs_struct *hvcsd = tty->driver_data; | 1263 | struct hvcs_struct *hvcsd = tty->driver_data; |
1288 | unsigned long flags; | 1264 | unsigned long flags; |
1289 | int temp_open_count; | 1265 | int temp_open_count; |
1290 | struct kobject *kobjp; | ||
1291 | int irq = NO_IRQ; | 1266 | int irq = NO_IRQ; |
1292 | 1267 | ||
1293 | spin_lock_irqsave(&hvcsd->lock, flags); | 1268 | spin_lock_irqsave(&hvcsd->lock, flags); |
1294 | /* Preserve this so that we know how many kobject refs to put */ | 1269 | /* Preserve this so that we know how many kref refs to put */ |
1295 | temp_open_count = hvcsd->open_count; | 1270 | temp_open_count = hvcsd->open_count; |
1296 | 1271 | ||
1297 | /* | 1272 | /* |
1298 | * Don't kobject put inside the spinlock because the destruction | 1273 | * Don't kref put inside the spinlock because the destruction |
1299 | * callback may use the spinlock and it may get called before the | 1274 | * callback may use the spinlock and it may get called before the |
1300 | * spinlock has been released. Get a pointer to the kobject and | 1275 | * spinlock has been released. |
1301 | * kobject_put on that after releasing the spinlock. | ||
1302 | */ | 1276 | */ |
1303 | kobjp = &hvcsd->kobj; | ||
1304 | |||
1305 | vio_disable_interrupts(hvcsd->vdev); | 1277 | vio_disable_interrupts(hvcsd->vdev); |
1306 | 1278 | ||
1307 | hvcsd->todo_mask = 0; | 1279 | hvcsd->todo_mask = 0; |
@@ -1324,7 +1296,7 @@ static void hvcs_hangup(struct tty_struct * tty) | |||
1324 | free_irq(irq, hvcsd); | 1296 | free_irq(irq, hvcsd); |
1325 | 1297 | ||
1326 | /* | 1298 | /* |
1327 | * We need to kobject_put() for every open_count we have since the | 1299 | * We need to kref_put() for every open_count we have since the |
1328 | * tty_hangup() function doesn't invoke a close per open connection on a | 1300 | * tty_hangup() function doesn't invoke a close per open connection on a |
1329 | * non-console device. | 1301 | * non-console device. |
1330 | */ | 1302 | */ |
@@ -1335,7 +1307,7 @@ static void hvcs_hangup(struct tty_struct * tty) | |||
1335 | * NOTE: If this hangup was signaled from user space then the | 1307 | * NOTE: If this hangup was signaled from user space then the |
1336 | * final put will never happen. | 1308 | * final put will never happen. |
1337 | */ | 1309 | */ |
1338 | kobject_put(kobjp); | 1310 | kref_put(&hvcsd->kref, destroy_hvcs_struct); |
1339 | } | 1311 | } |
1340 | } | 1312 | } |
1341 | 1313 | ||