* updated kollision (21.12.1 -> 21.12.2), untested
[t2-trunk.git] / architecture / powerpc64 / package / linux / 0210-ps3encdec.patch
blob1a20ad4a009ba691a5e4d8f0b97ba98ecce118b0
1 # --- T2-COPYRIGHT-NOTE-BEGIN ---
2 # This copyright note is auto-generated by scripts/Create-CopyPatch.
3 #
4 # T2 SDE: architecture/powerpc64/package/.../0210-ps3encdec.patch
5 # Copyright (C) 2020 The T2 SDE Project
6 #
7 # More information can be found in the files COPYING and README.
8 #
9 # This patch file is dual-licensed. It is available under the license the
10 # patched project is licensed under, as long as it is an OpenSource license
11 # as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms
12 # of the GNU General Public License as published by the Free Software
13 # Foundation; either version 2 of the License, or (at your option) any later
14 # version.
15 # --- T2-COPYRIGHT-NOTE-END ---
17 --- a/arch/powerpc/include/asm/ps3.h 2012-08-02 23:17:17.126972935 +0200
18 +++ b/arch/powerpc/include/asm/ps3.h 2012-08-06 19:41:56.754901977 +0200
19 @@ -328,6 +328,7 @@
20 PS3_MATCH_ID_LPM = 11,
21 PS3_MATCH_ID_STOR_NOR_FLASH = 12,
22 PS3_MATCH_ID_DISP_MANAGER = 13,
23 + PS3_MATCH_ID_STOR_ENCDEC = 14,
26 enum ps3_match_sub_id {
27 @@ -349,6 +350,7 @@
28 #define PS3_MODULE_ALIAS_LPM "ps3:11:0"
29 #define PS3_MODULE_ALIAS_STOR_NOR_FLASH "ps3:12:0"
30 #define PS3_MODULE_ALIAS_DISP_MANAGER "ps3:13:0"
31 +#define PS3_MODULE_ALIAS_STOR_ENCDEC "ps3:14:0"
33 enum ps3_system_bus_device_type {
34 PS3_DEVICE_TYPE_IOC0 = 1,
35 --- a/arch/powerpc/platforms/ps3/platform.h 2012-08-02 23:17:17.110306267 +0200
36 +++ b/arch/powerpc/platforms/ps3/platform.h 2012-08-06 19:42:30.948237298 +0200
37 @@ -89,6 +89,7 @@
38 PS3_DEV_TYPE_SB_GPIO = 6,
39 PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC, /* 14 */
40 PS3_DEV_TYPE_STOR_NOR_FLASH = 254,
41 + PS3_DEV_TYPE_STOR_ENCDEC = 255,
44 int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
45 --- a/arch/powerpc/platforms/ps3/device-init.c 2012-08-02 23:17:17.130306269 +0200
46 +++ b/arch/powerpc/platforms/ps3/device-init.c 2012-08-06 19:43:12.538239719 +0200
47 @@ -621,6 +621,13 @@
48 __func__, __LINE__);
49 break;
51 + case PS3_DEV_TYPE_STOR_ENCDEC:
52 + result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_ENCDEC);
53 + if (result)
54 + pr_debug("%s:%u ps3_setup_storage_dev failed\n",
55 + __func__, __LINE__);
56 + break;
58 default:
59 result = 0;
60 pr_debug("%s:%u: unsupported dev_type %u\n", __func__, __LINE__,
61 --- a/arch/powerpc/platforms/ps3/system-bus.c 2012-08-02 23:17:17.126972935 +0200
62 +++ b/arch/powerpc/platforms/ps3/system-bus.c 2012-08-06 19:44:03.851576042 +0200
63 @@ -175,6 +175,7 @@
64 case PS3_MATCH_ID_STOR_ROM:
65 case PS3_MATCH_ID_STOR_FLASH:
66 case PS3_MATCH_ID_STOR_NOR_FLASH:
67 + case PS3_MATCH_ID_STOR_ENCDEC:
68 return ps3_open_hv_device_sb(dev);
70 case PS3_MATCH_ID_SOUND:
71 @@ -215,6 +216,7 @@
72 case PS3_MATCH_ID_STOR_ROM:
73 case PS3_MATCH_ID_STOR_FLASH:
74 case PS3_MATCH_ID_STOR_NOR_FLASH:
75 + case PS3_MATCH_ID_STOR_ENCDEC:
76 return ps3_close_hv_device_sb(dev);
78 case PS3_MATCH_ID_SOUND:
79 --- a/drivers/ps3/ps3stor_lib.c 2012-08-02 23:17:17.100306267 +0200
80 +++ b/drivers/ps3/ps3stor_lib.c 2012-08-06 20:43:55.981785017 +0200
81 @@ -90,8 +90,9 @@
82 unsigned int i;
83 unsigned long n;
85 - if (dev->sbd.match_id == PS3_MATCH_ID_STOR_ROM) {
86 - /* special case: CD-ROM is assumed always accessible */
87 + if ((dev->sbd.match_id == PS3_MATCH_ID_STOR_ROM) ||
88 + (dev->sbd.match_id == PS3_MATCH_ID_STOR_ENCDEC)) {
89 + /* special case: CD-ROM and ENCDEC are assumed always accessible */
90 dev->accessible_regions = 1;
91 return 0;
93 --- a/arch/powerpc/platforms/ps3/Kconfig 2012-08-02 23:17:17.153639603 +0200
94 +++ b/arch/powerpc/platforms/ps3/Kconfig 2012-08-06 19:46:13.304916903 +0200
95 @@ -192,6 +192,16 @@
96 This driver allows you to create/delete/modify regions
97 on PS3 storage devices.
99 +config PS3_ENCDEC
100 + tristate "PS3 ENCDEC Driver"
101 + depends on PPC_PS3
102 + select PS3_STORAGE
103 + help
104 + Include support for the PS3 ENCDEC device.
106 + This support is required to access the PS3 ENCDEC device.
107 + In general, all users will say Y or M.
109 config PS3GELIC_UDBG
110 bool "PS3 udbg output via UDP broadcasts on Ethernet"
111 depends on PPC_PS3
112 --- a/drivers/char/Makefile 2018-12-26 11:36:10.222679391 +0100
113 +++ b/drivers/char/Makefile 2018-12-26 11:37:07.674950989 +0100
114 @@ -44,6 +44,7 @@
116 obj-$(CONFIG_PS3_FLASH) += ps3flash.o
117 obj-$(CONFIG_PS3_STRGMNGR) += ps3strgmngr.o
118 +obj-$(CONFIG_PS3_ENCDEC) += ps3encdec.o
120 obj-$(CONFIG_XILLYBUS) += xillybus/
121 obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o
122 --- /dev/null 2012-08-07 02:54:53.492474007 +0200
123 +++ b/drivers/char/ps3encdec.c 2012-08-07 02:56:38.822480157 +0200
124 @@ -0,0 +1,394 @@
126 + * PS3 ENCDEC Driver
128 + * Copyright (C) 2011 graf_chokolo <grafchokolo@gmail.com>
129 + * Copyright (C) 2011, 2012 glevand <geoffrey.levand@mail.ru>
130 + * Copyright (C) 2019-2021 René Rebe <rene@rebe.de>
131 + * All rights reserved.
133 + * This program is free software; you can redistribute it and/or modify it
134 + * under the terms of the GNU General Public License as published
135 + * by the Free Software Foundation; version 2 of the License.
137 + * This program is distributed in the hope that it will be useful, but
138 + * WITHOUT ANY WARRANTY; without even the implied warranty of
139 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
140 + * General Public License for more details.
142 + * You should have received a copy of the GNU General Public License along
143 + * with this program; if not, write to the Free Software Foundation, Inc.,
144 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
145 + */
147 +#include <linux/module.h>
148 +#include <linux/kernel.h>
149 +#include <linux/init.h>
150 +#include <linux/slab.h>
151 +#include <linux/fs.h>
152 +#include <linux/sched.h>
153 +#include <linux/mutex.h>
154 +#include <linux/poll.h>
155 +#include <linux/uaccess.h>
156 +#include <linux/compat.h>
157 +#include <linux/miscdevice.h>
158 +#include <linux/sched/signal.h>
160 +#include <asm/ps3.h>
161 +#include <asm/lv1call.h>
162 +#include <asm/ps3stor.h>
163 +#include <asm/firmware.h>
165 +#define DEVICE_NAME "ps3encdec"
167 +#define BOUNCE_SIZE (4 * 1024)
169 +struct ps3encdec_private
171 + struct ps3_storage_device *dev;
172 + struct miscdevice misc;
173 + char *bounce_wbuf;
174 + u64 bounce_wlpar;
175 + char *bounce_rbuf;
176 + u64 bounce_rlpar;
177 + struct mutex mtx;
178 + wait_queue_head_t read_wq;
179 + wait_queue_head_t write_wq;
180 + int cmd_done;
181 + int cmd_failed;
182 + int cmd_data_avail;
185 +static struct ps3encdec_private *ps3encdec_priv;
187 +static ssize_t ps3encdec_read(struct file *file, char __user *usrbuf,
188 + size_t count, loff_t *pos)
190 + struct ps3encdec_private *priv = ps3encdec_priv;
191 + int res = 0;
193 + if (mutex_lock_interruptible(&priv->mtx))
194 + return (-ERESTARTSYS);
196 + if (file->f_flags & O_NONBLOCK) {
197 + if (!priv->cmd_done || priv->cmd_failed)
198 + res = -EAGAIN;
199 + } else {
200 + DEFINE_WAIT(__wait);
202 + while (1) {
203 + prepare_to_wait(&priv->read_wq, &__wait, TASK_INTERRUPTIBLE);
205 + if (priv->cmd_data_avail)
206 + break;
208 + mutex_unlock(&priv->mtx);
210 + if (signal_pending(current)) {
211 + finish_wait(&priv->read_wq, &__wait);
212 + return (-ERESTARTSYS);
215 + schedule();
217 + res = mutex_lock_interruptible(&priv->mtx);
218 + if (res) {
219 + finish_wait(&priv->read_wq, &__wait);
220 + return (res);
224 + finish_wait(&priv->read_wq, &__wait);
227 + if (res)
228 + goto done;
230 + if (count > BOUNCE_SIZE)
231 + count = BOUNCE_SIZE;
233 + if (!count || (priv->cmd_done && priv->cmd_failed))
234 + goto done;
236 + if (copy_to_user(usrbuf, priv->bounce_rbuf + *pos, count)) {
237 + res = -EFAULT;
238 + goto done;
241 + priv->cmd_data_avail = 0;
243 + res = count;
245 +done:
247 + mutex_unlock(&priv->mtx);
249 + return (res);
252 +static ssize_t ps3encdec_write(struct file *file, const char __user *usrbuf,
253 + size_t count, loff_t *pos)
255 + struct ps3encdec_private *priv = ps3encdec_priv;
256 + struct ps3_storage_device *dev = priv->dev;
257 + u32 cmd;
258 + int res = 0;
260 + if (mutex_lock_interruptible(&priv->mtx))
261 + return (-ERESTARTSYS);
263 + if (file->f_flags & O_NONBLOCK) {
264 + if (!priv->cmd_done)
265 + res = -EAGAIN;
266 + } else {
267 + DEFINE_WAIT(__wait);
269 + while (1) {
270 + prepare_to_wait(&priv->write_wq, &__wait, TASK_INTERRUPTIBLE);
272 + if (priv->cmd_done)
273 + break;
275 + mutex_unlock(&priv->mtx);
277 + if (signal_pending(current)) {
278 + finish_wait(&priv->write_wq, &__wait);
279 + return (-ERESTARTSYS);
282 + schedule();
284 + res = mutex_lock_interruptible(&priv->mtx);
285 + if (res) {
286 + finish_wait(&priv->write_wq, &__wait);
287 + return (res);
291 + finish_wait(&priv->write_wq, &__wait);
294 + if (res)
295 + goto done;
297 + if (count > BOUNCE_SIZE + sizeof(cmd))
298 + count = BOUNCE_SIZE + sizeof(cmd);
300 + if (!count)
301 + goto done;
303 + if (count < sizeof(cmd)) {
304 + res = -EINVAL;
305 + goto done;
308 + if (copy_from_user(&cmd, usrbuf, sizeof(cmd))) {
309 + res = -EFAULT;
310 + goto done;
313 + if (copy_from_user(priv->bounce_wbuf, usrbuf + sizeof(cmd), count - sizeof(cmd))) {
314 + res = -EFAULT;
315 + goto done;
318 + priv->cmd_done = 0;
319 + priv->cmd_failed = 1;
320 + priv->cmd_data_avail = 0;
322 + res = lv1_storage_send_device_command(dev->sbd.dev_id, cmd,
323 + priv->bounce_wlpar, count - sizeof(cmd),
324 + priv->bounce_rlpar, BOUNCE_SIZE, &dev->tag);
325 + if (res) {
326 + dev_err(&dev->sbd.core, "%s:%u: res=%d\n",
327 + __func__, __LINE__, res);
328 + priv->cmd_done = 1;
329 + res = -EIO;
330 + goto done;
333 + res = count;
335 +done:
337 + mutex_unlock(&priv->mtx);
339 + return (res);
342 +static unsigned int ps3encdec_poll(struct file *file, poll_table *wait)
344 + struct ps3encdec_private *priv = ps3encdec_priv;
345 + unsigned int mask = 0;
347 + mutex_lock(&priv->mtx);
349 + poll_wait(file, &priv->read_wq, wait);
350 + poll_wait(file, &priv->write_wq, wait);
352 + if (priv->cmd_data_avail)
353 + mask |= POLLIN | POLLRDNORM;
355 + if (priv->cmd_done)
356 + mask |= POLLOUT | POLLWRNORM;
358 + mutex_unlock(&priv->mtx);
360 + return (mask);
363 +static irqreturn_t ps3encdec_interrupt(int irq, void *data)
365 + struct ps3_storage_device *dev = data;
366 + struct ps3encdec_private *priv;
367 + u64 tag, status;
368 + int res;
370 + res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
372 + pr_info("%s:%d: res=%d status=%llx\n", __func__, __LINE__, res, status);
374 + if (tag != dev->tag) {
375 + dev_err(&dev->sbd.core,
376 + "%s:%u: tag mismatch, got %llx, expected %llx\n",
377 + __func__, __LINE__, tag, dev->tag);
380 + if (res) {
381 + dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx\n",
382 + __func__, __LINE__, res, status);
383 + return (IRQ_HANDLED);
386 + priv = ps3_system_bus_get_drvdata(&dev->sbd);
388 + priv->cmd_done = 1;
389 + priv->cmd_failed = (status != 0);
390 + priv->cmd_data_avail = !priv->cmd_failed;
392 + wake_up_interruptible(&priv->read_wq);
393 + wake_up_interruptible(&priv->write_wq);
395 + return (IRQ_HANDLED);
398 +static const struct file_operations ps3encdec_fops = {
399 + .owner = THIS_MODULE,
400 + .open = nonseekable_open,
401 + .read = ps3encdec_read,
402 + .write = ps3encdec_write,
403 + .poll = ps3encdec_poll,
406 +static int ps3encdec_probe(struct ps3_system_bus_device *_dev)
408 + struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
409 + struct ps3encdec_private *priv;
410 + int res;
412 + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
413 + if (!priv)
414 + return (-ENOMEM);
416 + ps3_system_bus_set_drvdata(_dev, priv);
418 + dev->bounce_size = BOUNCE_SIZE * 2;
419 + dev->bounce_buf = kmalloc(dev->bounce_size, GFP_DMA);
420 + if (!dev->bounce_buf) {
421 + res = -ENOMEM;
422 + goto fail_free_priv;
425 + res = ps3stor_setup(dev, ps3encdec_interrupt);
426 + if (res)
427 + goto fail_free_bounce;
429 + mutex_init(&priv->mtx);
431 + init_waitqueue_head(&priv->read_wq);
432 + init_waitqueue_head(&priv->write_wq);
434 + priv->cmd_done = 1;
435 + priv->cmd_failed = 0;
436 + priv->cmd_data_avail = 0;
438 + priv->misc.minor = MISC_DYNAMIC_MINOR,
439 + priv->misc.name = DEVICE_NAME,
440 + priv->misc.fops = &ps3encdec_fops,
442 + res = misc_register(&priv->misc);
443 + if (res)
444 + goto fail_teardown;
446 + priv->dev = dev;
447 + priv->bounce_wbuf = dev->bounce_buf;
448 + priv->bounce_wlpar = dev->bounce_lpar;
449 + priv->bounce_rbuf = dev->bounce_buf + BOUNCE_SIZE;
450 + priv->bounce_rlpar = dev->bounce_lpar + BOUNCE_SIZE;
452 + ps3encdec_priv = priv;
454 + return (0);
456 +fail_teardown:
458 + ps3stor_teardown(dev);
460 +fail_free_bounce:
462 + kfree(dev->bounce_buf);
464 +fail_free_priv:
466 + kfree(priv);
467 + ps3_system_bus_set_drvdata(_dev, NULL);
469 + return (res);
472 +static void ps3encdec_remove(struct ps3_system_bus_device *_dev)
474 + struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
475 + struct ps3encdec_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
477 + ps3encdec_priv = NULL;
479 + misc_deregister(&priv->misc);
480 + ps3stor_teardown(dev);
481 + kfree(dev->bounce_buf);
482 + kfree(priv);
483 + ps3_system_bus_set_drvdata(_dev, NULL);
486 +static struct ps3_system_bus_driver ps3encdec = {
487 + .match_id = PS3_MATCH_ID_STOR_ENCDEC,
488 + .core.name = DEVICE_NAME,
489 + .core.owner = THIS_MODULE,
490 + .probe = ps3encdec_probe,
491 + .remove = ps3encdec_remove,
492 + .shutdown = ps3encdec_remove,
495 +static int __init ps3encdec_init(void)
497 + int res;
499 + if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
500 + return (-ENODEV);
502 + res = ps3_system_bus_driver_register(&ps3encdec);
504 + return (res);
507 +static void __exit ps3encdec_exit(void)
509 + ps3_system_bus_driver_unregister(&ps3encdec);
512 +module_init(ps3encdec_init);
513 +module_exit(ps3encdec_exit);
515 +MODULE_AUTHOR("glevand");
516 +MODULE_DESCRIPTION("PS3 ENCDEC Driver");
517 +MODULE_LICENSE("GPL");
518 +MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_ENCDEC);