History

ps3: Replace direct file operations by callback

Currently the FLASH database is updated by the kernel using file operations, meant for userspace only. While this works for us because copy_{from,to}_user() on powerpc can handle kernel pointers, this is unportable and a bad example. Replace the file operations by callbacks, registered by the ps3flash driver.

Geert Uytterhoeven committed 17 years ago

Commit a4e623f1 parent 47cb9963 files · +152 −87Browse files

Unified · Split

3 files
  1. arch/powerpc/include/asm/ps3.h +7 −0
  2. arch/powerpc/platforms/ps3/os-area.c +75 −63
  3. drivers/char/ps3flash.c +70 −24
arch/powerpc/include/asm/ps3.h+7−0
@@ -53,6 +53,13 @@ enum ps3_param_av_multi_out ps3_os_area_get_av_multi_out(void); · 52 unmodified lines
5353 extern u64 ps3_os_area_get_rtc_diff(void);
5454 extern void ps3_os_area_set_rtc_diff(u64 rtc_diff);
5555
56+struct ps3_os_area_flash_ops {
57+ ssize_t (*read)(void *buf, size_t count, loff_t pos);
58+ ssize_t (*write)(const void *buf, size_t count, loff_t pos);
59+};
60+
61+extern void ps3_os_area_flash_register(const struct ps3_os_area_flash_ops *ops);
62+
5663 /* dma routines */
5764
5865 enum ps3_dma_page_size {
arch/powerpc/platforms/ps3/os-area.c+75−63
@@ -226,6 +226,44 @@ static struct property property_av_multi_out = { · 225 unmodified lines
226226 .value = &saved_params.av_multi_out,
227227 };
228228
229+
230+static DEFINE_MUTEX(os_area_flash_mutex);
231+
232+static const struct ps3_os_area_flash_ops *os_area_flash_ops;
233+
234+void ps3_os_area_flash_register(const struct ps3_os_area_flash_ops *ops)
235+{
236+ mutex_lock(&os_area_flash_mutex);
237+ os_area_flash_ops = ops;
238+ mutex_unlock(&os_area_flash_mutex);
239+}
240+EXPORT_SYMBOL_GPL(ps3_os_area_flash_register);
241+
242+static ssize_t os_area_flash_read(void *buf, size_t count, loff_t pos)
243+{
244+ ssize_t res = -ENODEV;
245+
246+ mutex_lock(&os_area_flash_mutex);
247+ if (os_area_flash_ops)
248+ res = os_area_flash_ops->read(buf, count, pos);
249+ mutex_unlock(&os_area_flash_mutex);
250+
251+ return res;
252+}
253+
254+static ssize_t os_area_flash_write(const void *buf, size_t count, loff_t pos)
255+{
256+ ssize_t res = -ENODEV;
257+
258+ mutex_lock(&os_area_flash_mutex);
259+ if (os_area_flash_ops)
260+ res = os_area_flash_ops->write(buf, count, pos);
261+ mutex_unlock(&os_area_flash_mutex);
262+
263+ return res;
264+}
265+
266+
229267 /**
230268 * os_area_set_property - Add or overwrite a saved_params value to the device tree.
231269 *
@@ -352,12 +390,12 @@ static int db_verify(const struct os_area_db *db) · 120 unmodified lines
352390 if (memcmp(db->magic_num, OS_AREA_DB_MAGIC_NUM,
353391 sizeof(db->magic_num))) {
354392 pr_debug("%s:%d magic_num failed\n", __func__, __LINE__);
355− return -1;
393+ return -EINVAL;
356394 }
357395
358396 if (db->version != 1) {
359397 pr_debug("%s:%d version failed\n", __func__, __LINE__);
360− return -1;
398+ return -EINVAL;
361399 }
362400
363401 return 0;
@@ -578,59 +616,48 @@ static void os_area_db_init(struct os_area_db *db) · 214 unmodified lines
578616 *
579617 */
580618
581−static void __maybe_unused update_flash_db(void)
619+static int update_flash_db(void)
582620 {
583− int result;
584− int file;
585− off_t offset;
621+ const unsigned int buf_len = 8 * OS_AREA_SEGMENT_SIZE;
622+ struct os_area_header *header;
586623 ssize_t count;
587− static const unsigned int buf_len = 8 * OS_AREA_SEGMENT_SIZE;
588− const struct os_area_header *header;
624+ int error;
625+ loff_t pos;
589626 struct os_area_db* db;
590627
591628 /* Read in header and db from flash. */
592629
593− file = sys_open("/dev/ps3flash", O_RDWR, 0);
594−
595− if (file < 0) {
596− pr_debug("%s:%d sys_open failed\n", __func__, __LINE__);
597− goto fail_open;
598− }
599−
600630 header = kmalloc(buf_len, GFP_KERNEL);
601−
602631 if (!header) {
603− pr_debug("%s:%d kmalloc failed\n", __func__, __LINE__);
604− goto fail_malloc;
632+ pr_debug("%s: kmalloc failed\n", __func__);
633+ return -ENOMEM;
605634 }
606635
607− offset = sys_lseek(file, 0, SEEK_SET);
608−
609− if (offset != 0) {
610− pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__);
611− goto fail_header_seek;
636+ count = os_area_flash_read(header, buf_len, 0);
637+ if (count < 0) {
638+ pr_debug("%s: os_area_flash_read failed %zd\n", __func__,
639+ count);
640+ error = count;
641+ goto fail;
612642 }
613643
614− count = sys_read(file, (char __user *)header, buf_len);
615−
616− result = count < OS_AREA_SEGMENT_SIZE || verify_header(header)
617− || count < header->db_area_offset * OS_AREA_SEGMENT_SIZE;
618−
619− if (result) {
620− pr_debug("%s:%d verify_header failed\n", __func__, __LINE__);
644+ pos = header->db_area_offset * OS_AREA_SEGMENT_SIZE;
645+ if (count < OS_AREA_SEGMENT_SIZE || verify_header(header) ||
646+ count < pos) {
647+ pr_debug("%s: verify_header failed\n", __func__);
621648 dump_header(header);
622− goto fail_header;
649+ error = -EINVAL;
650+ goto fail;
623651 }
624652
625653 /* Now got a good db offset and some maybe good db data. */
626654
627− db = (void*)header + header->db_area_offset * OS_AREA_SEGMENT_SIZE;
655+ db = (void *)header + pos;
628656
629− result = db_verify(db);
630−
631− if (result) {
632− printk(KERN_NOTICE "%s:%d: Verify of flash database failed, "
633− "formatting.\n", __func__, __LINE__);
657+ error = db_verify(db);
658+ if (error) {
659+ pr_notice("%s: Verify of flash database failed, formatting.\n",
660+ __func__);
634661 dump_db(db);
635662 os_area_db_init(db);
636663 }
@@ -639,29 +666,16 @@ static void __maybe_unused update_flash_db(void) · 2 unmodified lines
639666
640667 db_set_64(db, &os_area_db_id_rtc_diff, saved_params.rtc_diff);
641668
642− offset = sys_lseek(file, header->db_area_offset * OS_AREA_SEGMENT_SIZE,
643− SEEK_SET);
644−
645− if (offset != header->db_area_offset * OS_AREA_SEGMENT_SIZE) {
646− pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__);
647− goto fail_db_seek;
648− }
649−
650− count = sys_write(file, (const char __user *)db,
651− sizeof(struct os_area_db));
652−
669+ count = os_area_flash_write(db, sizeof(struct os_area_db), pos);
653670 if (count < sizeof(struct os_area_db)) {
654− pr_debug("%s:%d sys_write failed\n", __func__, __LINE__);
671+ pr_debug("%s: os_area_flash_write failed %zd\n", __func__,
672+ count);
673+ error = count < 0 ? count : -EIO;
655674 }
656675
657−fail_db_seek:
658−fail_header:
659−fail_header_seek:
676+fail:
660677 kfree(header);
661−fail_malloc:
662− sys_close(file);
663−fail_open:
664− return;
678+ return error;
665679 }
666680
667681 /**
@@ -674,11 +688,11 @@ fail_open: · 6 unmodified lines
674688 static void os_area_queue_work_handler(struct work_struct *work)
675689 {
676690 struct device_node *node;
691+ int error;
677692
678693 pr_debug(" -> %s:%d\n", __func__, __LINE__);
679694
680695 node = of_find_node_by_path("/");
681−
682696 if (node) {
683697 os_area_set_property(node, &property_rtc_diff);
684698 of_node_put(node);
@@ -686,12 +700,10 @@ static void os_area_queue_work_handler(struct work_struct *work) · 1 unmodified line
686700 pr_debug("%s:%d of_find_node_by_path failed\n",
687701 __func__, __LINE__);
688702
689−#if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE)
690− update_flash_db();
691−#else
692− printk(KERN_WARNING "%s:%d: No flash rom driver configured.\n",
693− __func__, __LINE__);
694−#endif
703+ error = update_flash_db();
704+ if (error)
705+ pr_warning("%s: Could not update FLASH ROM\n", __func__);
706+
695707 pr_debug(" <- %s:%d\n", __func__, __LINE__);
696708 }
697709
drivers/char/ps3flash.c+70−24
@@ -104,18 +104,19 @@ out: · 103 unmodified lines
104104 return res;
105105 }
106106
107−static ssize_t ps3flash_read(struct file *file, char __user *buf, size_t count,
108− loff_t *pos)
107+static ssize_t ps3flash_read(char __user *userbuf, void *kernelbuf,
108+ size_t count, loff_t *pos)
109109 {
110110 struct ps3_storage_device *dev = ps3flash_dev;
111111 struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
112112 u64 size, start_sector, end_sector, offset;
113113 ssize_t sectors_read;
114114 size_t remaining, n;
115+ const void *src;
115116
116117 dev_dbg(&dev->sbd.core,
117− "%s:%u: Reading %zu bytes at position %lld to user 0x%p\n",
118− __func__, __LINE__, count, *pos, buf);
118+ "%s:%u: Reading %zu bytes at position %lld to U0x%p/K0x%p\n",
119+ __func__, __LINE__, count, *pos, userbuf, kernelbuf);
119120
120121 size = dev->regions[dev->region_idx].size*dev->blk_size;
121122 if (*pos >= size || !count)
@@ -145,19 +146,26 @@ static ssize_t ps3flash_read(struct file *file, char __user *buf, size_t count, · 23 unmodified lines
145146 }
146147
147148 n = min_t(u64, remaining, sectors_read*dev->blk_size-offset);
149+ src = dev->bounce_buf+offset;
148150 dev_dbg(&dev->sbd.core,
149− "%s:%u: copy %lu bytes from 0x%p to user 0x%p\n",
150− __func__, __LINE__, n, dev->bounce_buf+offset, buf);
151− if (copy_to_user(buf, dev->bounce_buf+offset, n)) {
152− mutex_unlock(&priv->mutex);
153− sectors_read = -EFAULT;
154− goto fail;
151+ "%s:%u: copy %lu bytes from 0x%p to U0x%p/K0x%p\n",
152+ __func__, __LINE__, n, src, userbuf, kernelbuf);
153+ if (userbuf) {
154+ if (copy_to_user(userbuf, src, n)) {
155+ mutex_unlock(&priv->mutex);
156+ sectors_read = -EFAULT;
157+ goto fail;
158+ }
159+ userbuf += n;
160+ }
161+ if (kernelbuf) {
162+ memcpy(kernelbuf, src, n);
163+ kernelbuf += n;
155164 }
156165
157166 mutex_unlock(&priv->mutex);
158167
159168 *pos += n;
160− buf += n;
161169 remaining -= n;
162170 start_sector += sectors_read;
163171 offset = 0;
@@ -169,8 +177,8 @@ fail: · 5 unmodified lines
169177 return sectors_read;
170178 }
171179
172−static ssize_t ps3flash_write(struct file *file, const char __user *buf,
173− size_t count, loff_t *pos)
180+static ssize_t ps3flash_write(const char __user *userbuf,
181+ const void *kernelbuf, size_t count, loff_t *pos)
174182 {
175183 struct ps3_storage_device *dev = ps3flash_dev;
176184 struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
@@ -179,10 +187,11 @@ static ssize_t ps3flash_write(struct file *file, const char __user *buf, · 2 unmodified lines
179187 ssize_t res;
180188 size_t remaining, n;
181189 unsigned int sec_off;
190+ void *dst;
182191
183192 dev_dbg(&dev->sbd.core,
184− "%s:%u: Writing %zu bytes at position %lld from user 0x%p\n",
185− __func__, __LINE__, count, *pos, buf);
193+ "%s:%u: Writing %zu bytes at position %lld from U0x%p/K0x%p\n",
194+ __func__, __LINE__, count, *pos, userbuf, kernelbuf);
186195
187196 size = dev->regions[dev->region_idx].size*dev->blk_size;
188197 if (*pos >= size || !count)
@@ -259,12 +268,20 @@ static ssize_t ps3flash_write(struct file *file, const char __user *buf, · 70 unmodified lines
259268 }
260269
261270 n = min_t(u64, remaining, dev->bounce_size-offset);
271+ dst = dev->bounce_buf+offset;
262272 dev_dbg(&dev->sbd.core,
263− "%s:%u: copy %lu bytes from user 0x%p to 0x%p\n",
264− __func__, __LINE__, n, buf, dev->bounce_buf+offset);
265− if (copy_from_user(dev->bounce_buf+offset, buf, n)) {
266− res = -EFAULT;
267− goto fail;
273+ "%s:%u: copy %lu bytes from U0x%p/K0x%p to 0x%p\n",
274+ __func__, __LINE__, n, userbuf, kernelbuf, dst);
275+ if (userbuf) {
276+ if (copy_from_user(dst, userbuf, n)) {
277+ res = -EFAULT;
278+ goto fail;
279+ }
280+ userbuf += n;
281+ }
282+ if (kernelbuf) {
283+ memcpy(dst, kernelbuf, n);
284+ kernelbuf += n;
268285 }
269286
270287 res = ps3flash_write_chunk(dev, start_write_sector);
@@ -274,7 +291,6 @@ static ssize_t ps3flash_write(struct file *file, const char __user *buf, · 3 unmodified lines
274291 mutex_unlock(&priv->mutex);
275292
276293 *pos += n;
277− buf += n;
278294 remaining -= n;
279295 start_write_sector += chunk_sectors;
280296 head = 0;
@@ -288,6 +304,29 @@ fail: · 7 unmodified lines
288304 return res;
289305 }
290306
307+static ssize_t ps3flash_user_read(struct file *file, char __user *buf,
308+ size_t count, loff_t *pos)
309+{
310+ return ps3flash_read(buf, NULL, count, pos);
311+}
312+
313+static ssize_t ps3flash_user_write(struct file *file, const char __user *buf,
314+ size_t count, loff_t *pos)
315+{
316+ return ps3flash_write(buf, NULL, count, pos);
317+}
318+
319+static ssize_t ps3flash_kernel_read(void *buf, size_t count, loff_t pos)
320+{
321+ return ps3flash_read(NULL, buf, count, &pos);
322+}
323+
324+static ssize_t ps3flash_kernel_write(const void *buf, size_t count,
325+ loff_t pos)
326+{
327+ return ps3flash_write(NULL, buf, count, &pos);
328+}
329+
291330
292331 static irqreturn_t ps3flash_interrupt(int irq, void *data)
293332 {
@@ -312,12 +351,16 @@ static irqreturn_t ps3flash_interrupt(int irq, void *data) · 18 unmodified lines
312351 return IRQ_HANDLED;
313352 }
314353
315−
316354 static const struct file_operations ps3flash_fops = {
317355 .owner = THIS_MODULE,
318356 .llseek = ps3flash_llseek,
319− .read = ps3flash_read,
320− .write = ps3flash_write,
357+ .read = ps3flash_user_read,
358+ .write = ps3flash_user_write,
359+};
360+
361+static const struct ps3_os_area_flash_ops ps3flash_kernel_ops = {
362+ .read = ps3flash_kernel_read,
363+ .write = ps3flash_kernel_write,
321364 };
322365
323366 static struct miscdevice ps3flash_misc = {
@@ -386,6 +429,8 @@ static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev) · 62 unmodified lines
386429
387430 dev_info(&dev->sbd.core, "%s:%u: registered misc device %d\n",
388431 __func__, __LINE__, ps3flash_misc.minor);
432+
433+ ps3_os_area_flash_register(&ps3flash_kernel_ops);
389434 return 0;
390435
391436 fail_teardown:
@@ -402,6 +447,7 @@ static int ps3flash_remove(struct ps3_system_bus_device *_dev) · 10 unmodified lines
402447 {
403448 struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
404449
450+ ps3_os_area_flash_register(NULL);
405451 misc_deregister(&ps3flash_misc);
406452 ps3stor_teardown(dev);
407453 kfree(ps3_system_bus_get_drvdata(&dev->sbd));