Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: make usb class a const structure

Now that the driver core allows for struct class to be in read-only
memory, remove the usb_class structure and create the usbmisc_class
const class structure declared at build time which places it into
read-only memory, instead of having it to be dynamically allocated
at load time.

Additionally, now we register usb class at startup and unregister it
when shutting down, so we don't have to count uses of the class.
Therefore we don't need the 'usb_class' structure anymore. Due to this
fact, remove all static functions related to class initialization and
deinitialization. We can't use them in 'usb.c' since they are static
and we don't really need them anymore.

Since we have to register the class in usb_init function in 'usb.c'
and use it in 'file.c' as well, declare the usbmisc_class structure
as 'export' in the 'usb.h' file.

Debatable moment: the class registration and unregistration functions
could be extracted to the 'file.c'. I think we don't want to do this
since it would be one-line functions. They would make the code paths
more confusing and add calling overhead.

Suggested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ivan Orlov <ivan.orlov0322@gmail.com>
Link: https://lore.kernel.org/r/20230621202514.1223670-1-ivan.orlov0322@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Ivan Orlov and committed by
Greg Kroah-Hartman
015fbdde 2319b9c8

+14 -61
+7 -61
drivers/usb/core/file.c
··· 29 29 #define MAX_USB_MINORS 256 30 30 static const struct file_operations *usb_minors[MAX_USB_MINORS]; 31 31 static DECLARE_RWSEM(minor_rwsem); 32 - static DEFINE_MUTEX(init_usb_class_mutex); 33 32 34 33 static int usb_open(struct inode *inode, struct file *file) 35 34 { ··· 56 57 .llseek = noop_llseek, 57 58 }; 58 59 59 - static struct usb_class { 60 - struct kref kref; 61 - struct class *class; 62 - } *usb_class; 63 - 64 60 static char *usb_devnode(const struct device *dev, umode_t *mode) 65 61 { 66 62 struct usb_class_driver *drv; ··· 66 72 return drv->devnode(dev, mode); 67 73 } 68 74 69 - static int init_usb_class(void) 70 - { 71 - int result = 0; 72 - 73 - if (usb_class != NULL) { 74 - kref_get(&usb_class->kref); 75 - goto exit; 76 - } 77 - 78 - usb_class = kmalloc(sizeof(*usb_class), GFP_KERNEL); 79 - if (!usb_class) { 80 - result = -ENOMEM; 81 - goto exit; 82 - } 83 - 84 - kref_init(&usb_class->kref); 85 - usb_class->class = class_create("usbmisc"); 86 - if (IS_ERR(usb_class->class)) { 87 - result = PTR_ERR(usb_class->class); 88 - printk(KERN_ERR "class_create failed for usb devices\n"); 89 - kfree(usb_class); 90 - usb_class = NULL; 91 - goto exit; 92 - } 93 - usb_class->class->devnode = usb_devnode; 94 - 95 - exit: 96 - return result; 97 - } 98 - 99 - static void release_usb_class(struct kref *kref) 100 - { 101 - /* Ok, we cheat as we know we only have one usb_class */ 102 - class_destroy(usb_class->class); 103 - kfree(usb_class); 104 - usb_class = NULL; 105 - } 106 - 107 - static void destroy_usb_class(void) 108 - { 109 - mutex_lock(&init_usb_class_mutex); 110 - kref_put(&usb_class->kref, release_usb_class); 111 - mutex_unlock(&init_usb_class_mutex); 112 - } 75 + const struct class usbmisc_class = { 76 + .name = "usbmisc", 77 + .devnode = usb_devnode, 78 + }; 113 79 114 80 int usb_major_init(void) 115 81 { ··· 110 156 int usb_register_dev(struct usb_interface *intf, 111 157 struct usb_class_driver *class_driver) 112 158 { 113 - int retval; 159 + int retval = 0; 114 160 int minor_base = class_driver->minor_base; 115 161 int minor; 116 162 char name[20]; ··· 128 174 return -EINVAL; 129 175 if (intf->minor >= 0) 130 176 return -EADDRINUSE; 131 - 132 - mutex_lock(&init_usb_class_mutex); 133 - retval = init_usb_class(); 134 - mutex_unlock(&init_usb_class_mutex); 135 - 136 - if (retval) 137 - return retval; 138 177 139 178 dev_dbg(&intf->dev, "looking for a minor, starting at %d\n", minor_base); 140 179 ··· 147 200 148 201 /* create a usb class device for this usb interface */ 149 202 snprintf(name, sizeof(name), class_driver->name, minor - minor_base); 150 - intf->usb_dev = device_create(usb_class->class, &intf->dev, 203 + intf->usb_dev = device_create(&usbmisc_class, &intf->dev, 151 204 MKDEV(USB_MAJOR, minor), class_driver, 152 205 "%s", kbasename(name)); 153 206 if (IS_ERR(intf->usb_dev)) { ··· 181 234 return; 182 235 183 236 dev_dbg(&intf->dev, "removing %d minor\n", intf->minor); 184 - device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); 237 + device_destroy(&usbmisc_class, MKDEV(USB_MAJOR, intf->minor)); 185 238 186 239 down_write(&minor_rwsem); 187 240 usb_minors[intf->minor] = NULL; ··· 189 242 190 243 intf->usb_dev = NULL; 191 244 intf->minor = -1; 192 - destroy_usb_class(); 193 245 } 194 246 EXPORT_SYMBOL_GPL(usb_deregister_dev);
+6
drivers/usb/core/usb.c
··· 1101 1101 retval = usb_major_init(); 1102 1102 if (retval) 1103 1103 goto major_init_failed; 1104 + retval = class_register(&usbmisc_class); 1105 + if (retval) 1106 + goto class_register_failed; 1104 1107 retval = usb_register(&usbfs_driver); 1105 1108 if (retval) 1106 1109 goto driver_register_failed; ··· 1123 1120 usb_devio_init_failed: 1124 1121 usb_deregister(&usbfs_driver); 1125 1122 driver_register_failed: 1123 + class_unregister(&usbmisc_class); 1124 + class_register_failed: 1126 1125 usb_major_cleanup(); 1127 1126 major_init_failed: 1128 1127 bus_unregister_notifier(&usb_bus_type, &usb_bus_nb); ··· 1152 1147 usb_deregister(&usbfs_driver); 1153 1148 usb_devio_cleanup(); 1154 1149 usb_hub_cleanup(); 1150 + class_unregister(&usbmisc_class); 1155 1151 bus_unregister_notifier(&usb_bus_type, &usb_bus_nb); 1156 1152 bus_unregister(&usb_bus_type); 1157 1153 usb_acpi_unregister();
+1
drivers/usb/core/usb.h
··· 141 141 142 142 #endif 143 143 144 + extern const struct class usbmisc_class; 144 145 extern const struct bus_type usb_bus_type; 145 146 extern struct mutex usb_port_peer_mutex; 146 147 extern struct device_type usb_device_type;