aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ps3
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ps3')
-rw-r--r--drivers/ps3/Makefile5
-rw-r--r--drivers/ps3/ps3av.c372
-rw-r--r--drivers/ps3/ps3av_cmd.c51
-rw-r--r--drivers/ps3/ps3stor_lib.c302
-rw-r--r--drivers/ps3/sys-manager-core.c68
-rw-r--r--drivers/ps3/sys-manager.c290
-rw-r--r--drivers/ps3/vuart.c817
-rw-r--r--drivers/ps3/vuart.h71
8 files changed, 1293 insertions, 683 deletions
diff --git a/drivers/ps3/Makefile b/drivers/ps3/Makefile
index e251d1c1171c..746031de2195 100644
--- a/drivers/ps3/Makefile
+++ b/drivers/ps3/Makefile
@@ -1,3 +1,6 @@
1obj-$(CONFIG_PS3_VUART) += vuart.o 1obj-$(CONFIG_PS3_VUART) += vuart.o
2obj-$(CONFIG_PS3_PS3AV) += ps3av.o ps3av_cmd.o 2obj-$(CONFIG_PS3_PS3AV) += ps3av_mod.o
3ps3av_mod-objs += ps3av.o ps3av_cmd.o
4obj-$(CONFIG_PPC_PS3) += sys-manager-core.o
3obj-$(CONFIG_PS3_SYS_MANAGER) += sys-manager.o 5obj-$(CONFIG_PS3_SYS_MANAGER) += sys-manager.o
6obj-$(CONFIG_PS3_STORAGE) += ps3stor_lib.o
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c
index 1393e64335f9..85e21614f868 100644
--- a/drivers/ps3/ps3av.c
+++ b/drivers/ps3/ps3av.c
@@ -1,32 +1,30 @@
1/* 1/*
2 * Copyright (C) 2006 Sony Computer Entertainment Inc. 2 * PS3 AV backend support.
3 * Copyright 2006, 2007 Sony Corporation
4 * 3 *
5 * AV backend support for PS3 4 * Copyright (C) 2007 Sony Computer Entertainment Inc.
5 * Copyright 2007 Sony Corp.
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify
8 * under the terms of the GNU General Public License as published 8 * it under the terms of the GNU General Public License as published by
9 * by the Free Software Foundation; version 2 of the License. 9 * the Free Software Foundation; version 2 of the License.
10 * 10 *
11 * This program is distributed in the hope that it will be useful, but 11 * This program is distributed in the hope that it will be useful,
12 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * General Public License for more details. 14 * GNU General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GNU General Public License along 16 * You should have received a copy of the GNU General Public License
17 * with this program; if not, write to the Free Software Foundation, Inc., 17 * along with this program; if not, write to the Free Software
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */ 19 */
20 20
21#include <linux/kernel.h>
21#include <linux/module.h> 22#include <linux/module.h>
22#include <linux/delay.h> 23#include <linux/delay.h>
23#include <linux/notifier.h> 24#include <linux/notifier.h>
24#include <linux/reboot.h>
25#include <linux/kernel.h>
26#include <linux/ioctl.h> 25#include <linux/ioctl.h>
27 26
28#include <asm/firmware.h> 27#include <asm/firmware.h>
29#include <asm/lv1call.h>
30#include <asm/ps3av.h> 28#include <asm/ps3av.h>
31#include <asm/ps3.h> 29#include <asm/ps3.h>
32 30
@@ -39,13 +37,12 @@ static int timeout = 5000; /* in msec ( 5 sec ) */
39module_param(timeout, int, 0644); 37module_param(timeout, int, 0644);
40 38
41static struct ps3av { 39static struct ps3av {
42 int available;
43 struct mutex mutex; 40 struct mutex mutex;
44 struct work_struct work; 41 struct work_struct work;
45 struct completion done; 42 struct completion done;
46 struct workqueue_struct *wq; 43 struct workqueue_struct *wq;
47 int open_count; 44 int open_count;
48 struct ps3_vuart_port_device *dev; 45 struct ps3_system_bus_device *dev;
49 46
50 int region; 47 int region;
51 struct ps3av_pkt_av_get_hw_conf av_hw_conf; 48 struct ps3av_pkt_av_get_hw_conf av_hw_conf;
@@ -55,11 +52,13 @@ static struct ps3av {
55 u32 audio_port; 52 u32 audio_port;
56 int ps3av_mode; 53 int ps3av_mode;
57 int ps3av_mode_old; 54 int ps3av_mode_old;
58} ps3av; 55 union {
59 56 struct ps3av_reply_hdr reply_hdr;
60static struct ps3_vuart_port_device ps3av_dev = { 57 u8 raw[PS3AV_BUF_SIZE];
61 .match_id = PS3_MATCH_ID_AV_SETTINGS 58 } recv_buf;
62}; 59 void (*flip_ctl)(int on, void *data);
60 void *flip_data;
61} *ps3av;
63 62
64/* color space */ 63/* color space */
65#define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8 64#define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8
@@ -169,7 +168,7 @@ static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr)
169 if (hdr->cid & PS3AV_EVENT_CMD_MASK) { 168 if (hdr->cid & PS3AV_EVENT_CMD_MASK) {
170 table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK); 169 table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK);
171 if (table) 170 if (table)
172 dev_dbg(&ps3av_dev.core, 171 dev_dbg(&ps3av->dev->core,
173 "recv event packet cid:%08x port:0x%x size:%d\n", 172 "recv event packet cid:%08x port:0x%x size:%d\n",
174 hdr->cid, ps3av_event_get_port_id(hdr->cid), 173 hdr->cid, ps3av_event_get_port_id(hdr->cid),
175 hdr->size); 174 hdr->size);
@@ -182,6 +181,41 @@ static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr)
182 return 0; 181 return 0;
183} 182}
184 183
184
185#define POLLING_INTERVAL 25 /* in msec */
186
187static int ps3av_vuart_write(struct ps3_system_bus_device *dev,
188 const void *buf, unsigned long size)
189{
190 int error;
191 dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
192 error = ps3_vuart_write(dev, buf, size);
193 dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
194 return error ? error : size;
195}
196
197static int ps3av_vuart_read(struct ps3_system_bus_device *dev, void *buf,
198 unsigned long size, int timeout)
199{
200 int error;
201 int loopcnt = 0;
202
203 dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
204 timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL;
205 while (loopcnt++ <= timeout) {
206 error = ps3_vuart_read(dev, buf, size);
207 if (!error)
208 return size;
209 if (error != -EAGAIN) {
210 printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
211 __func__, error);
212 return error;
213 }
214 msleep(POLLING_INTERVAL);
215 }
216 return -EWOULDBLOCK;
217}
218
185static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf, 219static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
186 struct ps3av_reply_hdr *recv_buf, int write_len, 220 struct ps3av_reply_hdr *recv_buf, int write_len,
187 int read_len) 221 int read_len)
@@ -190,13 +224,13 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
190 u32 cmd; 224 u32 cmd;
191 int event; 225 int event;
192 226
193 if (!ps3av.available) 227 if (!ps3av)
194 return -ENODEV; 228 return -ENODEV;
195 229
196 /* send pkt */ 230 /* send pkt */
197 res = ps3av_vuart_write(ps3av.dev, send_buf, write_len); 231 res = ps3av_vuart_write(ps3av->dev, send_buf, write_len);
198 if (res < 0) { 232 if (res < 0) {
199 dev_dbg(&ps3av_dev.core, 233 dev_dbg(&ps3av->dev->core,
200 "%s: ps3av_vuart_write() failed (result=%d)\n", 234 "%s: ps3av_vuart_write() failed (result=%d)\n",
201 __func__, res); 235 __func__, res);
202 return res; 236 return res;
@@ -206,20 +240,20 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
206 cmd = send_buf->cid; 240 cmd = send_buf->cid;
207 do { 241 do {
208 /* read header */ 242 /* read header */
209 res = ps3av_vuart_read(ps3av.dev, recv_buf, PS3AV_HDR_SIZE, 243 res = ps3av_vuart_read(ps3av->dev, recv_buf, PS3AV_HDR_SIZE,
210 timeout); 244 timeout);
211 if (res != PS3AV_HDR_SIZE) { 245 if (res != PS3AV_HDR_SIZE) {
212 dev_dbg(&ps3av_dev.core, 246 dev_dbg(&ps3av->dev->core,
213 "%s: ps3av_vuart_read() failed (result=%d)\n", 247 "%s: ps3av_vuart_read() failed (result=%d)\n",
214 __func__, res); 248 __func__, res);
215 return res; 249 return res;
216 } 250 }
217 251
218 /* read body */ 252 /* read body */
219 res = ps3av_vuart_read(ps3av.dev, &recv_buf->cid, 253 res = ps3av_vuart_read(ps3av->dev, &recv_buf->cid,
220 recv_buf->size, timeout); 254 recv_buf->size, timeout);
221 if (res < 0) { 255 if (res < 0) {
222 dev_dbg(&ps3av_dev.core, 256 dev_dbg(&ps3av->dev->core,
223 "%s: ps3av_vuart_read() failed (result=%d)\n", 257 "%s: ps3av_vuart_read() failed (result=%d)\n",
224 __func__, res); 258 __func__, res);
225 return res; 259 return res;
@@ -230,7 +264,7 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
230 } while (event); 264 } while (event);
231 265
232 if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) { 266 if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) {
233 dev_dbg(&ps3av_dev.core, "%s: reply err (result=%x)\n", 267 dev_dbg(&ps3av->dev->core, "%s: reply err (result=%x)\n",
234 __func__, recv_buf->cid); 268 __func__, recv_buf->cid);
235 return -EINVAL; 269 return -EINVAL;
236 } 270 }
@@ -245,7 +279,7 @@ static int ps3av_process_reply_packet(struct ps3av_send_hdr *cmd_buf,
245 int return_len; 279 int return_len;
246 280
247 if (recv_buf->version != PS3AV_VERSION) { 281 if (recv_buf->version != PS3AV_VERSION) {
248 dev_dbg(&ps3av_dev.core, "reply_packet invalid version:%x\n", 282 dev_dbg(&ps3av->dev->core, "reply_packet invalid version:%x\n",
249 recv_buf->version); 283 recv_buf->version);
250 return -EFAULT; 284 return -EFAULT;
251 } 285 }
@@ -267,16 +301,11 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
267 struct ps3av_send_hdr *buf) 301 struct ps3av_send_hdr *buf)
268{ 302{
269 int res = 0; 303 int res = 0;
270 static union {
271 struct ps3av_reply_hdr reply_hdr;
272 u8 raw[PS3AV_BUF_SIZE];
273 } recv_buf;
274
275 u32 *table; 304 u32 *table;
276 305
277 BUG_ON(!ps3av.available); 306 BUG_ON(!ps3av);
278 307
279 mutex_lock(&ps3av.mutex); 308 mutex_lock(&ps3av->mutex);
280 309
281 table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK); 310 table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK);
282 BUG_ON(!table); 311 BUG_ON(!table);
@@ -288,7 +317,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
288 ps3av_set_hdr(cid, send_len, buf); 317 ps3av_set_hdr(cid, send_len, buf);
289 318
290 /* send packet via vuart */ 319 /* send packet via vuart */
291 res = ps3av_send_cmd_pkt(buf, &recv_buf.reply_hdr, send_len, 320 res = ps3av_send_cmd_pkt(buf, &ps3av->recv_buf.reply_hdr, send_len,
292 usr_buf_size); 321 usr_buf_size);
293 if (res < 0) { 322 if (res < 0) {
294 printk(KERN_ERR 323 printk(KERN_ERR
@@ -298,7 +327,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
298 } 327 }
299 328
300 /* process reply packet */ 329 /* process reply packet */
301 res = ps3av_process_reply_packet(buf, &recv_buf.reply_hdr, 330 res = ps3av_process_reply_packet(buf, &ps3av->recv_buf.reply_hdr,
302 usr_buf_size); 331 usr_buf_size);
303 if (res < 0) { 332 if (res < 0) {
304 printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n", 333 printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n",
@@ -306,11 +335,11 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
306 goto err; 335 goto err;
307 } 336 }
308 337
309 mutex_unlock(&ps3av.mutex); 338 mutex_unlock(&ps3av->mutex);
310 return 0; 339 return 0;
311 340
312 err: 341 err:
313 mutex_unlock(&ps3av.mutex); 342 mutex_unlock(&ps3av->mutex);
314 printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res); 343 printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res);
315 return res; 344 return res;
316} 345}
@@ -319,11 +348,11 @@ static int ps3av_set_av_video_mute(u32 mute)
319{ 348{
320 int i, num_of_av_port, res; 349 int i, num_of_av_port, res;
321 350
322 num_of_av_port = ps3av.av_hw_conf.num_of_hdmi + 351 num_of_av_port = ps3av->av_hw_conf.num_of_hdmi +
323 ps3av.av_hw_conf.num_of_avmulti; 352 ps3av->av_hw_conf.num_of_avmulti;
324 /* video mute on */ 353 /* video mute on */
325 for (i = 0; i < num_of_av_port; i++) { 354 for (i = 0; i < num_of_av_port; i++) {
326 res = ps3av_cmd_av_video_mute(1, &ps3av.av_port[i], mute); 355 res = ps3av_cmd_av_video_mute(1, &ps3av->av_port[i], mute);
327 if (res < 0) 356 if (res < 0)
328 return -1; 357 return -1;
329 } 358 }
@@ -335,13 +364,13 @@ static int ps3av_set_video_disable_sig(void)
335{ 364{
336 int i, num_of_hdmi_port, num_of_av_port, res; 365 int i, num_of_hdmi_port, num_of_av_port, res;
337 366
338 num_of_hdmi_port = ps3av.av_hw_conf.num_of_hdmi; 367 num_of_hdmi_port = ps3av->av_hw_conf.num_of_hdmi;
339 num_of_av_port = ps3av.av_hw_conf.num_of_hdmi + 368 num_of_av_port = ps3av->av_hw_conf.num_of_hdmi +
340 ps3av.av_hw_conf.num_of_avmulti; 369 ps3av->av_hw_conf.num_of_avmulti;
341 370
342 /* tv mute */ 371 /* tv mute */
343 for (i = 0; i < num_of_hdmi_port; i++) { 372 for (i = 0; i < num_of_hdmi_port; i++) {
344 res = ps3av_cmd_av_tv_mute(ps3av.av_port[i], 373 res = ps3av_cmd_av_tv_mute(ps3av->av_port[i],
345 PS3AV_CMD_MUTE_ON); 374 PS3AV_CMD_MUTE_ON);
346 if (res < 0) 375 if (res < 0)
347 return -1; 376 return -1;
@@ -350,11 +379,11 @@ static int ps3av_set_video_disable_sig(void)
350 379
351 /* video mute on */ 380 /* video mute on */
352 for (i = 0; i < num_of_av_port; i++) { 381 for (i = 0; i < num_of_av_port; i++) {
353 res = ps3av_cmd_av_video_disable_sig(ps3av.av_port[i]); 382 res = ps3av_cmd_av_video_disable_sig(ps3av->av_port[i]);
354 if (res < 0) 383 if (res < 0)
355 return -1; 384 return -1;
356 if (i < num_of_hdmi_port) { 385 if (i < num_of_hdmi_port) {
357 res = ps3av_cmd_av_tv_mute(ps3av.av_port[i], 386 res = ps3av_cmd_av_tv_mute(ps3av->av_port[i],
358 PS3AV_CMD_MUTE_OFF); 387 PS3AV_CMD_MUTE_OFF);
359 if (res < 0) 388 if (res < 0)
360 return -1; 389 return -1;
@@ -369,17 +398,17 @@ static int ps3av_set_audio_mute(u32 mute)
369{ 398{
370 int i, num_of_av_port, num_of_opt_port, res; 399 int i, num_of_av_port, num_of_opt_port, res;
371 400
372 num_of_av_port = ps3av.av_hw_conf.num_of_hdmi + 401 num_of_av_port = ps3av->av_hw_conf.num_of_hdmi +
373 ps3av.av_hw_conf.num_of_avmulti; 402 ps3av->av_hw_conf.num_of_avmulti;
374 num_of_opt_port = ps3av.av_hw_conf.num_of_spdif; 403 num_of_opt_port = ps3av->av_hw_conf.num_of_spdif;
375 404
376 for (i = 0; i < num_of_av_port; i++) { 405 for (i = 0; i < num_of_av_port; i++) {
377 res = ps3av_cmd_av_audio_mute(1, &ps3av.av_port[i], mute); 406 res = ps3av_cmd_av_audio_mute(1, &ps3av->av_port[i], mute);
378 if (res < 0) 407 if (res < 0)
379 return -1; 408 return -1;
380 } 409 }
381 for (i = 0; i < num_of_opt_port; i++) { 410 for (i = 0; i < num_of_opt_port; i++) {
382 res = ps3av_cmd_audio_mute(1, &ps3av.opt_port[i], mute); 411 res = ps3av_cmd_audio_mute(1, &ps3av->opt_port[i], mute);
383 if (res < 0) 412 if (res < 0)
384 return -1; 413 return -1;
385 } 414 }
@@ -394,40 +423,40 @@ int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source)
394 struct ps3av_pkt_audio_mode audio_mode; 423 struct ps3av_pkt_audio_mode audio_mode;
395 u32 len = 0; 424 u32 len = 0;
396 425
397 num_of_audio = ps3av.av_hw_conf.num_of_hdmi + 426 num_of_audio = ps3av->av_hw_conf.num_of_hdmi +
398 ps3av.av_hw_conf.num_of_avmulti + 427 ps3av->av_hw_conf.num_of_avmulti +
399 ps3av.av_hw_conf.num_of_spdif; 428 ps3av->av_hw_conf.num_of_spdif;
400 429
401 avb_param.num_of_video_pkt = 0; 430 avb_param.num_of_video_pkt = 0;
402 avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO; /* always 0 */ 431 avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO; /* always 0 */
403 avb_param.num_of_av_video_pkt = 0; 432 avb_param.num_of_av_video_pkt = 0;
404 avb_param.num_of_av_audio_pkt = ps3av.av_hw_conf.num_of_hdmi; 433 avb_param.num_of_av_audio_pkt = ps3av->av_hw_conf.num_of_hdmi;
405 434
406 vid = video_mode_table[ps3av.ps3av_mode].vid; 435 vid = video_mode_table[ps3av->ps3av_mode].vid;
407 436
408 /* audio mute */ 437 /* audio mute */
409 ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON); 438 ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON);
410 439
411 /* audio inactive */ 440 /* audio inactive */
412 res = ps3av_cmd_audio_active(0, ps3av.audio_port); 441 res = ps3av_cmd_audio_active(0, ps3av->audio_port);
413 if (res < 0) 442 if (res < 0)
414 dev_dbg(&ps3av_dev.core, 443 dev_dbg(&ps3av->dev->core,
415 "ps3av_cmd_audio_active OFF failed\n"); 444 "ps3av_cmd_audio_active OFF failed\n");
416 445
417 /* audio_pkt */ 446 /* audio_pkt */
418 for (i = 0; i < num_of_audio; i++) { 447 for (i = 0; i < num_of_audio; i++) {
419 ps3av_cmd_set_audio_mode(&audio_mode, ps3av.av_port[i], ch, fs, 448 ps3av_cmd_set_audio_mode(&audio_mode, ps3av->av_port[i], ch,
420 word_bits, format, source); 449 fs, word_bits, format, source);
421 if (i < ps3av.av_hw_conf.num_of_hdmi) { 450 if (i < ps3av->av_hw_conf.num_of_hdmi) {
422 /* hdmi only */ 451 /* hdmi only */
423 len += ps3av_cmd_set_av_audio_param(&avb_param.buf[len], 452 len += ps3av_cmd_set_av_audio_param(&avb_param.buf[len],
424 ps3av.av_port[i], 453 ps3av->av_port[i],
425 &audio_mode, vid); 454 &audio_mode, vid);
426 } 455 }
427 /* audio_mode pkt should be sent separately */ 456 /* audio_mode pkt should be sent separately */
428 res = ps3av_cmd_audio_mode(&audio_mode); 457 res = ps3av_cmd_audio_mode(&audio_mode);
429 if (res < 0) 458 if (res < 0)
430 dev_dbg(&ps3av_dev.core, 459 dev_dbg(&ps3av->dev->core,
431 "ps3av_cmd_audio_mode failed, port:%x\n", i); 460 "ps3av_cmd_audio_mode failed, port:%x\n", i);
432 } 461 }
433 462
@@ -435,15 +464,16 @@ int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source)
435 len += offsetof(struct ps3av_pkt_avb_param, buf); 464 len += offsetof(struct ps3av_pkt_avb_param, buf);
436 res = ps3av_cmd_avb_param(&avb_param, len); 465 res = ps3av_cmd_avb_param(&avb_param, len);
437 if (res < 0) 466 if (res < 0)
438 dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n"); 467 dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n");
439 468
440 /* audio mute */ 469 /* audio mute */
441 ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF); 470 ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF);
442 471
443 /* audio active */ 472 /* audio active */
444 res = ps3av_cmd_audio_active(1, ps3av.audio_port); 473 res = ps3av_cmd_audio_active(1, ps3av->audio_port);
445 if (res < 0) 474 if (res < 0)
446 dev_dbg(&ps3av_dev.core, "ps3av_cmd_audio_active ON failed\n"); 475 dev_dbg(&ps3av->dev->core,
476 "ps3av_cmd_audio_active ON failed\n");
447 477
448 return 0; 478 return 0;
449} 479}
@@ -456,7 +486,7 @@ static int ps3av_set_videomode(void)
456 ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON); 486 ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON);
457 487
458 /* wake up ps3avd to do the actual video mode setting */ 488 /* wake up ps3avd to do the actual video mode setting */
459 queue_work(ps3av.wq, &ps3av.work); 489 queue_work(ps3av->wq, &ps3av->work);
460 490
461 return 0; 491 return 0;
462} 492}
@@ -473,8 +503,8 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
473 503
474 avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO; /* num of head */ 504 avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO; /* num of head */
475 avb_param.num_of_audio_pkt = 0; 505 avb_param.num_of_audio_pkt = 0;
476 avb_param.num_of_av_video_pkt = ps3av.av_hw_conf.num_of_hdmi + 506 avb_param.num_of_av_video_pkt = ps3av->av_hw_conf.num_of_hdmi +
477 ps3av.av_hw_conf.num_of_avmulti; 507 ps3av->av_hw_conf.num_of_avmulti;
478 avb_param.num_of_av_audio_pkt = 0; 508 avb_param.num_of_av_audio_pkt = 0;
479 509
480 /* video signal off */ 510 /* video signal off */
@@ -484,21 +514,21 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
484 if (id & PS3AV_MODE_HDCP_OFF) { 514 if (id & PS3AV_MODE_HDCP_OFF) {
485 res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF); 515 res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF);
486 if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) 516 if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
487 dev_dbg(&ps3av_dev.core, "Not supported\n"); 517 dev_dbg(&ps3av->dev->core, "Not supported\n");
488 else if (res) 518 else if (res)
489 dev_dbg(&ps3av_dev.core, 519 dev_dbg(&ps3av->dev->core,
490 "ps3av_cmd_av_hdmi_mode failed\n"); 520 "ps3av_cmd_av_hdmi_mode failed\n");
491 } else if (old_id & PS3AV_MODE_HDCP_OFF) { 521 } else if (old_id & PS3AV_MODE_HDCP_OFF) {
492 res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL); 522 res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL);
493 if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) 523 if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
494 dev_dbg(&ps3av_dev.core, 524 dev_dbg(&ps3av->dev->core,
495 "ps3av_cmd_av_hdmi_mode failed\n"); 525 "ps3av_cmd_av_hdmi_mode failed\n");
496 } 526 }
497 527
498 /* video_pkt */ 528 /* video_pkt */
499 for (i = 0; i < avb_param.num_of_video_pkt; i++) 529 for (i = 0; i < avb_param.num_of_video_pkt; i++)
500 len += ps3av_cmd_set_video_mode(&avb_param.buf[len], 530 len += ps3av_cmd_set_video_mode(&avb_param.buf[len],
501 ps3av.head[i], video_mode->vid, 531 ps3av->head[i], video_mode->vid,
502 video_mode->fmt, id); 532 video_mode->fmt, id);
503 /* av_video_pkt */ 533 /* av_video_pkt */
504 for (i = 0; i < avb_param.num_of_av_video_pkt; i++) { 534 for (i = 0; i < avb_param.num_of_av_video_pkt; i++) {
@@ -507,12 +537,12 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
507 else 537 else
508 av_video_cs = video_mode->cs; 538 av_video_cs = video_mode->cs;
509#ifndef PS3AV_HDMI_YUV 539#ifndef PS3AV_HDMI_YUV
510 if (ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 || 540 if (ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 ||
511 ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_1) 541 ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_1)
512 av_video_cs = RGB8; /* use RGB for HDMI */ 542 av_video_cs = RGB8; /* use RGB for HDMI */
513#endif 543#endif
514 len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len], 544 len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len],
515 ps3av.av_port[i], 545 ps3av->av_port[i],
516 video_mode->vid, av_video_cs, 546 video_mode->vid, av_video_cs,
517 video_mode->aspect, id); 547 video_mode->aspect, id);
518 } 548 }
@@ -524,7 +554,7 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
524 "%s: Command failed. Please try your request again. \n", 554 "%s: Command failed. Please try your request again. \n",
525 __func__); 555 __func__);
526 else if (res) 556 else if (res)
527 dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n"); 557 dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n");
528 558
529 msleep(1500); 559 msleep(1500);
530 /* av video mute */ 560 /* av video mute */
@@ -533,8 +563,8 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
533 563
534static void ps3avd(struct work_struct *work) 564static void ps3avd(struct work_struct *work)
535{ 565{
536 ps3av_set_videomode_cont(ps3av.ps3av_mode, ps3av.ps3av_mode_old); 566 ps3av_set_videomode_cont(ps3av->ps3av_mode, ps3av->ps3av_mode_old);
537 complete(&ps3av.done); 567 complete(&ps3av->done);
538} 568}
539 569
540static int ps3av_vid2table_id(int vid) 570static int ps3av_vid2table_id(int vid)
@@ -601,7 +631,7 @@ static int ps3av_hdmi_get_vid(struct ps3av_info_monitor *info)
601 return vid; 631 return vid;
602 } 632 }
603 633
604 if (ps3av.region & PS3AV_REGION_60) 634 if (ps3av->region & PS3AV_REGION_60)
605 vid = PS3AV_DEFAULT_HDMI_VID_REG_60; 635 vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
606 else 636 else
607 vid = PS3AV_DEFAULT_HDMI_VID_REG_50; 637 vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
@@ -643,16 +673,16 @@ static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf,
643 vid = PS3AV_DEFAULT_DVI_VID; 673 vid = PS3AV_DEFAULT_DVI_VID;
644 } else if (vid == -1) { 674 } else if (vid == -1) {
645 /* no HDMI interface or HDMI is off */ 675 /* no HDMI interface or HDMI is off */
646 if (ps3av.region & PS3AV_REGION_60) 676 if (ps3av->region & PS3AV_REGION_60)
647 vid = PS3AV_DEFAULT_AVMULTI_VID_REG_60; 677 vid = PS3AV_DEFAULT_AVMULTI_VID_REG_60;
648 else 678 else
649 vid = PS3AV_DEFAULT_AVMULTI_VID_REG_50; 679 vid = PS3AV_DEFAULT_AVMULTI_VID_REG_50;
650 if (ps3av.region & PS3AV_REGION_RGB) 680 if (ps3av->region & PS3AV_REGION_RGB)
651 rgb = PS3AV_MODE_RGB; 681 rgb = PS3AV_MODE_RGB;
652 } else if (boot) { 682 } else if (boot) {
653 /* HDMI: using DEFAULT HDMI_VID while booting up */ 683 /* HDMI: using DEFAULT HDMI_VID while booting up */
654 info = &monitor_info.info; 684 info = &monitor_info.info;
655 if (ps3av.region & PS3AV_REGION_60) { 685 if (ps3av->region & PS3AV_REGION_60) {
656 if (info->res_60.res_bits & PS3AV_RESBIT_720x480P) 686 if (info->res_60.res_bits & PS3AV_RESBIT_720x480P)
657 vid = PS3AV_DEFAULT_HDMI_VID_REG_60; 687 vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
658 else if (info->res_50.res_bits & PS3AV_RESBIT_720x576P) 688 else if (info->res_50.res_bits & PS3AV_RESBIT_720x576P)
@@ -715,14 +745,14 @@ int ps3av_set_video_mode(u32 id, int boot)
715 745
716 size = ARRAY_SIZE(video_mode_table); 746 size = ARRAY_SIZE(video_mode_table);
717 if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) { 747 if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) {
718 dev_dbg(&ps3av_dev.core, "%s: error id :%d\n", __func__, id); 748 dev_dbg(&ps3av->dev->core, "%s: error id :%d\n", __func__, id);
719 return -EINVAL; 749 return -EINVAL;
720 } 750 }
721 751
722 /* auto mode */ 752 /* auto mode */
723 option = id & ~PS3AV_MODE_MASK; 753 option = id & ~PS3AV_MODE_MASK;
724 if ((id & PS3AV_MODE_MASK) == 0) { 754 if ((id & PS3AV_MODE_MASK) == 0) {
725 id = ps3av_auto_videomode(&ps3av.av_hw_conf, boot); 755 id = ps3av_auto_videomode(&ps3av->av_hw_conf, boot);
726 if (id < 1) { 756 if (id < 1) {
727 printk(KERN_ERR "%s: invalid id :%d\n", __func__, id); 757 printk(KERN_ERR "%s: invalid id :%d\n", __func__, id);
728 return -EINVAL; 758 return -EINVAL;
@@ -731,11 +761,11 @@ int ps3av_set_video_mode(u32 id, int boot)
731 } 761 }
732 762
733 /* set videomode */ 763 /* set videomode */
734 wait_for_completion(&ps3av.done); 764 wait_for_completion(&ps3av->done);
735 ps3av.ps3av_mode_old = ps3av.ps3av_mode; 765 ps3av->ps3av_mode_old = ps3av->ps3av_mode;
736 ps3av.ps3av_mode = id; 766 ps3av->ps3av_mode = id;
737 if (ps3av_set_videomode()) 767 if (ps3av_set_videomode())
738 ps3av.ps3av_mode = ps3av.ps3av_mode_old; 768 ps3av->ps3av_mode = ps3av->ps3av_mode_old;
739 769
740 return 0; 770 return 0;
741} 771}
@@ -744,7 +774,7 @@ EXPORT_SYMBOL_GPL(ps3av_set_video_mode);
744 774
745int ps3av_get_auto_mode(int boot) 775int ps3av_get_auto_mode(int boot)
746{ 776{
747 return ps3av_auto_videomode(&ps3av.av_hw_conf, boot); 777 return ps3av_auto_videomode(&ps3av->av_hw_conf, boot);
748} 778}
749 779
750EXPORT_SYMBOL_GPL(ps3av_get_auto_mode); 780EXPORT_SYMBOL_GPL(ps3av_get_auto_mode);
@@ -772,7 +802,7 @@ EXPORT_SYMBOL_GPL(ps3av_set_mode);
772 802
773int ps3av_get_mode(void) 803int ps3av_get_mode(void)
774{ 804{
775 return ps3av.ps3av_mode; 805 return ps3av ? ps3av->ps3av_mode : 0;
776} 806}
777 807
778EXPORT_SYMBOL_GPL(ps3av_get_mode); 808EXPORT_SYMBOL_GPL(ps3av_get_mode);
@@ -842,82 +872,65 @@ int ps3av_audio_mute(int mute)
842 872
843EXPORT_SYMBOL_GPL(ps3av_audio_mute); 873EXPORT_SYMBOL_GPL(ps3av_audio_mute);
844 874
845int ps3av_dev_open(void) 875void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data),
876 void *flip_data)
846{ 877{
847 int status = 0; 878 mutex_lock(&ps3av->mutex);
848 879 ps3av->flip_ctl = flip_ctl;
849 mutex_lock(&ps3av.mutex); 880 ps3av->flip_data = flip_data;
850 if (!ps3av.open_count++) { 881 mutex_unlock(&ps3av->mutex);
851 status = lv1_gpu_open(0);
852 if (status) {
853 printk(KERN_ERR "%s: lv1_gpu_open failed %d\n",
854 __func__, status);
855 ps3av.open_count--;
856 }
857 }
858 mutex_unlock(&ps3av.mutex);
859
860 return status;
861} 882}
883EXPORT_SYMBOL_GPL(ps3av_register_flip_ctl);
862 884
863EXPORT_SYMBOL_GPL(ps3av_dev_open); 885void ps3av_flip_ctl(int on)
864
865int ps3av_dev_close(void)
866{ 886{
867 int status = 0; 887 mutex_lock(&ps3av->mutex);
868 888 if (ps3av->flip_ctl)
869 mutex_lock(&ps3av.mutex); 889 ps3av->flip_ctl(on, ps3av->flip_data);
870 if (ps3av.open_count <= 0) { 890 mutex_unlock(&ps3av->mutex);
871 printk(KERN_ERR "%s: GPU already closed\n", __func__);
872 status = -1;
873 } else if (!--ps3av.open_count) {
874 status = lv1_gpu_close();
875 if (status)
876 printk(KERN_WARNING "%s: lv1_gpu_close failed %d\n",
877 __func__, status);
878 }
879 mutex_unlock(&ps3av.mutex);
880
881 return status;
882} 891}
883 892
884EXPORT_SYMBOL_GPL(ps3av_dev_close); 893static int ps3av_probe(struct ps3_system_bus_device *dev)
885
886static int ps3av_probe(struct ps3_vuart_port_device *dev)
887{ 894{
888 int res; 895 int res;
889 u32 id; 896 u32 id;
890 897
891 dev_dbg(&ps3av_dev.core, "init ...\n"); 898 dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
892 dev_dbg(&ps3av_dev.core, " timeout=%d\n", timeout); 899 dev_dbg(&dev->core, " timeout=%d\n", timeout);
893 900
894 memset(&ps3av, 0, sizeof(ps3av)); 901 if (ps3av) {
895 902 dev_err(&dev->core, "Only one ps3av device is supported\n");
896 mutex_init(&ps3av.mutex); 903 return -EBUSY;
897 ps3av.ps3av_mode = 0; 904 }
898 ps3av.dev = dev;
899 905
900 INIT_WORK(&ps3av.work, ps3avd); 906 ps3av = kzalloc(sizeof(*ps3av), GFP_KERNEL);
901 init_completion(&ps3av.done); 907 if (!ps3av)
902 complete(&ps3av.done);
903 ps3av.wq = create_singlethread_workqueue("ps3avd");
904 if (!ps3av.wq)
905 return -ENOMEM; 908 return -ENOMEM;
906 909
907 ps3av.available = 1; 910 mutex_init(&ps3av->mutex);
911 ps3av->ps3av_mode = 0;
912 ps3av->dev = dev;
913
914 INIT_WORK(&ps3av->work, ps3avd);
915 init_completion(&ps3av->done);
916 complete(&ps3av->done);
917 ps3av->wq = create_singlethread_workqueue("ps3avd");
918 if (!ps3av->wq)
919 goto fail;
920
908 switch (ps3_os_area_get_av_multi_out()) { 921 switch (ps3_os_area_get_av_multi_out()) {
909 case PS3_PARAM_AV_MULTI_OUT_NTSC: 922 case PS3_PARAM_AV_MULTI_OUT_NTSC:
910 ps3av.region = PS3AV_REGION_60; 923 ps3av->region = PS3AV_REGION_60;
911 break; 924 break;
912 case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR: 925 case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR:
913 case PS3_PARAM_AV_MULTI_OUT_SECAM: 926 case PS3_PARAM_AV_MULTI_OUT_SECAM:
914 ps3av.region = PS3AV_REGION_50; 927 ps3av->region = PS3AV_REGION_50;
915 break; 928 break;
916 case PS3_PARAM_AV_MULTI_OUT_PAL_RGB: 929 case PS3_PARAM_AV_MULTI_OUT_PAL_RGB:
917 ps3av.region = PS3AV_REGION_50 | PS3AV_REGION_RGB; 930 ps3av->region = PS3AV_REGION_50 | PS3AV_REGION_RGB;
918 break; 931 break;
919 default: 932 default:
920 ps3av.region = PS3AV_REGION_60; 933 ps3av->region = PS3AV_REGION_60;
921 break; 934 break;
922 } 935 }
923 936
@@ -927,39 +940,47 @@ static int ps3av_probe(struct ps3_vuart_port_device *dev)
927 printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __func__, 940 printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __func__,
928 res); 941 res);
929 942
930 ps3av_get_hw_conf(&ps3av); 943 ps3av_get_hw_conf(ps3av);
931 id = ps3av_auto_videomode(&ps3av.av_hw_conf, 1); 944 id = ps3av_auto_videomode(&ps3av->av_hw_conf, 1);
932 mutex_lock(&ps3av.mutex); 945 mutex_lock(&ps3av->mutex);
933 ps3av.ps3av_mode = id; 946 ps3av->ps3av_mode = id;
934 mutex_unlock(&ps3av.mutex); 947 mutex_unlock(&ps3av->mutex);
935 948
936 dev_dbg(&ps3av_dev.core, "init...done\n"); 949 dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
937 950
938 return 0; 951 return 0;
952
953fail:
954 kfree(ps3av);
955 ps3av = NULL;
956 return -ENOMEM;
939} 957}
940 958
941static int ps3av_remove(struct ps3_vuart_port_device *dev) 959static int ps3av_remove(struct ps3_system_bus_device *dev)
942{ 960{
943 if (ps3av.available) { 961 dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
962 if (ps3av) {
944 ps3av_cmd_fin(); 963 ps3av_cmd_fin();
945 if (ps3av.wq) 964 if (ps3av->wq)
946 destroy_workqueue(ps3av.wq); 965 destroy_workqueue(ps3av->wq);
947 ps3av.available = 0; 966 kfree(ps3av);
967 ps3av = NULL;
948 } 968 }
949 969
970 dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
950 return 0; 971 return 0;
951} 972}
952 973
953static void ps3av_shutdown(struct ps3_vuart_port_device *dev) 974static void ps3av_shutdown(struct ps3_system_bus_device *dev)
954{ 975{
976 dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
955 ps3av_remove(dev); 977 ps3av_remove(dev);
978 dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
956} 979}
957 980
958static struct ps3_vuart_port_driver ps3av_driver = { 981static struct ps3_vuart_port_driver ps3av_driver = {
959 .match_id = PS3_MATCH_ID_AV_SETTINGS, 982 .core.match_id = PS3_MATCH_ID_AV_SETTINGS,
960 .core = { 983 .core.core.name = "ps3_av",
961 .name = "ps3_av",
962 },
963 .probe = ps3av_probe, 984 .probe = ps3av_probe,
964 .remove = ps3av_remove, 985 .remove = ps3av_remove,
965 .shutdown = ps3av_shutdown, 986 .shutdown = ps3av_shutdown,
@@ -972,6 +993,8 @@ static int ps3av_module_init(void)
972 if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) 993 if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
973 return -ENODEV; 994 return -ENODEV;
974 995
996 pr_debug(" -> %s:%d\n", __func__, __LINE__);
997
975 error = ps3_vuart_port_driver_register(&ps3av_driver); 998 error = ps3_vuart_port_driver_register(&ps3av_driver);
976 if (error) { 999 if (error) {
977 printk(KERN_ERR 1000 printk(KERN_ERR
@@ -980,20 +1003,21 @@ static int ps3av_module_init(void)
980 return error; 1003 return error;
981 } 1004 }
982 1005
983 error = ps3_vuart_port_device_register(&ps3av_dev); 1006 pr_debug(" <- %s:%d\n", __func__, __LINE__);
984 if (error)
985 printk(KERN_ERR
986 "%s: ps3_vuart_port_device_register failed %d\n",
987 __func__, error);
988
989 return error; 1007 return error;
990} 1008}
991 1009
992static void __exit ps3av_module_exit(void) 1010static void __exit ps3av_module_exit(void)
993{ 1011{
994 device_unregister(&ps3av_dev.core); 1012 pr_debug(" -> %s:%d\n", __func__, __LINE__);
995 ps3_vuart_port_driver_unregister(&ps3av_driver); 1013 ps3_vuart_port_driver_unregister(&ps3av_driver);
1014 pr_debug(" <- %s:%d\n", __func__, __LINE__);
996} 1015}
997 1016
998subsys_initcall(ps3av_module_init); 1017subsys_initcall(ps3av_module_init);
999module_exit(ps3av_module_exit); 1018module_exit(ps3av_module_exit);
1019
1020MODULE_LICENSE("GPL v2");
1021MODULE_DESCRIPTION("PS3 AV Settings Driver");
1022MODULE_AUTHOR("Sony Computer Entertainment Inc.");
1023MODULE_ALIAS(PS3_MODULE_ALIAS_AV_SETTINGS);
diff --git a/drivers/ps3/ps3av_cmd.c b/drivers/ps3/ps3av_cmd.c
index 0145ea173c42..f72f5ddf18e4 100644
--- a/drivers/ps3/ps3av_cmd.c
+++ b/drivers/ps3/ps3av_cmd.c
@@ -143,6 +143,14 @@ static u32 ps3av_vid_video2av(int vid)
143 return PS3AV_CMD_AV_VID_480P; 143 return PS3AV_CMD_AV_VID_480P;
144} 144}
145 145
146static int ps3av_hdmi_range(void)
147{
148 if (ps3_compare_firmware_version(1, 8, 0) < 0)
149 return 0;
150 else
151 return 1; /* supported */
152}
153
146int ps3av_cmd_init(void) 154int ps3av_cmd_init(void)
147{ 155{
148 int res; 156 int res;
@@ -350,6 +358,10 @@ u32 ps3av_cmd_set_av_video_cs(void *p, u32 avport, int video_vid, int cs_out,
350 /* should be same as video_mode.video_cs_out */ 358 /* should be same as video_mode.video_cs_out */
351 av_video_cs->av_cs_in = ps3av_cs_video2av(PS3AV_CMD_VIDEO_CS_RGB_8); 359 av_video_cs->av_cs_in = ps3av_cs_video2av(PS3AV_CMD_VIDEO_CS_RGB_8);
352 av_video_cs->bitlen_out = ps3av_cs_video2av_bitlen(cs_out); 360 av_video_cs->bitlen_out = ps3av_cs_video2av_bitlen(cs_out);
361 if ((id & PS3AV_MODE_WHITE) && ps3av_hdmi_range())
362 av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_ON;
363 else /* default off */
364 av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_OFF;
353 av_video_cs->aspect = aspect; 365 av_video_cs->aspect = aspect;
354 if (id & PS3AV_MODE_DITHER) { 366 if (id & PS3AV_MODE_DITHER) {
355 av_video_cs->dither = PS3AV_CMD_AV_DITHER_ON 367 av_video_cs->dither = PS3AV_CMD_AV_DITHER_ON
@@ -392,6 +404,10 @@ u32 ps3av_cmd_set_video_mode(void *p, u32 head, int video_vid, int video_fmt,
392 video_mode->pitch = video_mode->width * 4; /* line_length */ 404 video_mode->pitch = video_mode->width * 4; /* line_length */
393 video_mode->video_out_format = PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT; 405 video_mode->video_out_format = PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT;
394 video_mode->video_format = ps3av_video_fmt_table[video_fmt].format; 406 video_mode->video_format = ps3av_video_fmt_table[video_fmt].format;
407 if ((id & PS3AV_MODE_COLOR) && ps3av_hdmi_range())
408 video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT;
409 else /* default enable */
410 video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT;
395 video_mode->video_order = ps3av_video_fmt_table[video_fmt].order; 411 video_mode->video_order = ps3av_video_fmt_table[video_fmt].order;
396 412
397 pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n", 413 pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n",
@@ -852,7 +868,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len)
852{ 868{
853 int res; 869 int res;
854 870
855 ps3fb_flip_ctl(0); /* flip off */ 871 ps3av_flip_ctl(0); /* flip off */
856 872
857 /* avb packet */ 873 /* avb packet */
858 res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb), 874 res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb),
@@ -866,7 +882,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len)
866 res); 882 res);
867 883
868 out: 884 out:
869 ps3fb_flip_ctl(1); /* flip on */ 885 ps3av_flip_ctl(1); /* flip on */
870 return res; 886 return res;
871} 887}
872 888
@@ -987,34 +1003,3 @@ void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *
987 | PS3AV_CMD_AV_LAYOUT_176 \ 1003 | PS3AV_CMD_AV_LAYOUT_176 \
988 | PS3AV_CMD_AV_LAYOUT_192) 1004 | PS3AV_CMD_AV_LAYOUT_192)
989 1005
990/************************* vuart ***************************/
991
992#define POLLING_INTERVAL 25 /* in msec */
993
994int ps3av_vuart_write(struct ps3_vuart_port_device *dev, const void *buf,
995 unsigned long size)
996{
997 int error = ps3_vuart_write(dev, buf, size);
998 return error ? error : size;
999}
1000
1001int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
1002 unsigned long size, int timeout)
1003{
1004 int error;
1005 int loopcnt = 0;
1006
1007 timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL;
1008 while (loopcnt++ <= timeout) {
1009 error = ps3_vuart_read(dev, buf, size);
1010 if (!error)
1011 return size;
1012 if (error != -EAGAIN) {
1013 printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
1014 __func__, error);
1015 return error;
1016 }
1017 msleep(POLLING_INTERVAL);
1018 }
1019 return -EWOULDBLOCK;
1020}
diff --git a/drivers/ps3/ps3stor_lib.c b/drivers/ps3/ps3stor_lib.c
new file mode 100644
index 000000000000..3a9824e3b251
--- /dev/null
+++ b/drivers/ps3/ps3stor_lib.c
@@ -0,0 +1,302 @@
1/*
2 * PS3 Storage Library
3 *
4 * Copyright (C) 2007 Sony Computer Entertainment Inc.
5 * Copyright 2007 Sony Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include <linux/dma-mapping.h>
22
23#include <asm/lv1call.h>
24#include <asm/ps3stor.h>
25
26
27static int ps3stor_probe_access(struct ps3_storage_device *dev)
28{
29 int res, error;
30 unsigned int i;
31 unsigned long n;
32
33 if (dev->sbd.match_id == PS3_MATCH_ID_STOR_ROM) {
34 /* special case: CD-ROM is assumed always accessible */
35 dev->accessible_regions = 1;
36 return 0;
37 }
38
39 error = -EPERM;
40 for (i = 0; i < dev->num_regions; i++) {
41 dev_dbg(&dev->sbd.core,
42 "%s:%u: checking accessibility of region %u\n",
43 __func__, __LINE__, i);
44
45 dev->region_idx = i;
46 res = ps3stor_read_write_sectors(dev, dev->bounce_lpar, 0, 1,
47 0);
48 if (res) {
49 dev_dbg(&dev->sbd.core, "%s:%u: read failed, "
50 "region %u is not accessible\n", __func__,
51 __LINE__, i);
52 continue;
53 }
54
55 dev_dbg(&dev->sbd.core, "%s:%u: region %u is accessible\n",
56 __func__, __LINE__, i);
57 set_bit(i, &dev->accessible_regions);
58
59 /* We can access at least one region */
60 error = 0;
61 }
62 if (error)
63 return error;
64
65 n = hweight_long(dev->accessible_regions);
66 if (n > 1)
67 dev_info(&dev->sbd.core,
68 "%s:%u: %lu accessible regions found. Only the first "
69 "one will be used",
70 __func__, __LINE__, n);
71 dev->region_idx = __ffs(dev->accessible_regions);
72 dev_info(&dev->sbd.core,
73 "First accessible region has index %u start %lu size %lu\n",
74 dev->region_idx, dev->regions[dev->region_idx].start,
75 dev->regions[dev->region_idx].size);
76
77 return 0;
78}
79
80
81/**
82 * ps3stor_setup - Setup a storage device before use
83 * @dev: Pointer to a struct ps3_storage_device
84 * @handler: Pointer to an interrupt handler
85 *
86 * Returns 0 for success, or an error code
87 */
88int ps3stor_setup(struct ps3_storage_device *dev, irq_handler_t handler)
89{
90 int error, res, alignment;
91 enum ps3_dma_page_size page_size;
92
93 error = ps3_open_hv_device(&dev->sbd);
94 if (error) {
95 dev_err(&dev->sbd.core,
96 "%s:%u: ps3_open_hv_device failed %d\n", __func__,
97 __LINE__, error);
98 goto fail;
99 }
100
101 error = ps3_sb_event_receive_port_setup(&dev->sbd, PS3_BINDING_CPU_ANY,
102 &dev->irq);
103 if (error) {
104 dev_err(&dev->sbd.core,
105 "%s:%u: ps3_sb_event_receive_port_setup failed %d\n",
106 __func__, __LINE__, error);
107 goto fail_close_device;
108 }
109
110 error = request_irq(dev->irq, handler, IRQF_DISABLED,
111 dev->sbd.core.driver->name, dev);
112 if (error) {
113 dev_err(&dev->sbd.core, "%s:%u: request_irq failed %d\n",
114 __func__, __LINE__, error);
115 goto fail_sb_event_receive_port_destroy;
116 }
117
118 alignment = min(__ffs(dev->bounce_size),
119 __ffs((unsigned long)dev->bounce_buf));
120 if (alignment < 12) {
121 dev_err(&dev->sbd.core,
122 "%s:%u: bounce buffer not aligned (%lx at 0x%p)\n",
123 __func__, __LINE__, dev->bounce_size, dev->bounce_buf);
124 error = -EINVAL;
125 goto fail_free_irq;
126 } else if (alignment < 16)
127 page_size = PS3_DMA_4K;
128 else
129 page_size = PS3_DMA_64K;
130 dev->sbd.d_region = &dev->dma_region;
131 ps3_dma_region_init(&dev->sbd, &dev->dma_region, page_size,
132 PS3_DMA_OTHER, dev->bounce_buf, dev->bounce_size);
133 res = ps3_dma_region_create(&dev->dma_region);
134 if (res) {
135 dev_err(&dev->sbd.core, "%s:%u: cannot create DMA region\n",
136 __func__, __LINE__);
137 error = -ENOMEM;
138 goto fail_free_irq;
139 }
140
141 dev->bounce_lpar = ps3_mm_phys_to_lpar(__pa(dev->bounce_buf));
142 dev->bounce_dma = dma_map_single(&dev->sbd.core, dev->bounce_buf,
143 dev->bounce_size, DMA_BIDIRECTIONAL);
144 if (!dev->bounce_dma) {
145 dev_err(&dev->sbd.core, "%s:%u: map DMA region failed\n",
146 __func__, __LINE__);
147 error = -ENODEV;
148 goto fail_free_dma;
149 }
150
151 error = ps3stor_probe_access(dev);
152 if (error) {
153 dev_err(&dev->sbd.core, "%s:%u: No accessible regions found\n",
154 __func__, __LINE__);
155 goto fail_unmap_dma;
156 }
157 return 0;
158
159fail_unmap_dma:
160 dma_unmap_single(&dev->sbd.core, dev->bounce_dma, dev->bounce_size,
161 DMA_BIDIRECTIONAL);
162fail_free_dma:
163 ps3_dma_region_free(&dev->dma_region);
164fail_free_irq:
165 free_irq(dev->irq, dev);
166fail_sb_event_receive_port_destroy:
167 ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq);
168fail_close_device:
169 ps3_close_hv_device(&dev->sbd);
170fail:
171 return error;
172}
173EXPORT_SYMBOL_GPL(ps3stor_setup);
174
175
176/**
177 * ps3stor_teardown - Tear down a storage device after use
178 * @dev: Pointer to a struct ps3_storage_device
179 */
180void ps3stor_teardown(struct ps3_storage_device *dev)
181{
182 int error;
183
184 dma_unmap_single(&dev->sbd.core, dev->bounce_dma, dev->bounce_size,
185 DMA_BIDIRECTIONAL);
186 ps3_dma_region_free(&dev->dma_region);
187
188 free_irq(dev->irq, dev);
189
190 error = ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq);
191 if (error)
192 dev_err(&dev->sbd.core,
193 "%s:%u: destroy event receive port failed %d\n",
194 __func__, __LINE__, error);
195
196 error = ps3_close_hv_device(&dev->sbd);
197 if (error)
198 dev_err(&dev->sbd.core,
199 "%s:%u: ps3_close_hv_device failed %d\n", __func__,
200 __LINE__, error);
201}
202EXPORT_SYMBOL_GPL(ps3stor_teardown);
203
204
205/**
206 * ps3stor_read_write_sectors - read/write from/to a storage device
207 * @dev: Pointer to a struct ps3_storage_device
208 * @lpar: HV logical partition address
209 * @start_sector: First sector to read/write
210 * @sectors: Number of sectors to read/write
211 * @write: Flag indicating write (non-zero) or read (zero)
212 *
213 * Returns 0 for success, -1 in case of failure to submit the command, or
214 * an LV1 status value in case of other errors
215 */
216u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
217 u64 start_sector, u64 sectors, int write)
218{
219 unsigned int region_id = dev->regions[dev->region_idx].id;
220 const char *op = write ? "write" : "read";
221 int res;
222
223 dev_dbg(&dev->sbd.core, "%s:%u: %s %lu sectors starting at %lu\n",
224 __func__, __LINE__, op, sectors, start_sector);
225
226 init_completion(&dev->done);
227 res = write ? lv1_storage_write(dev->sbd.dev_id, region_id,
228 start_sector, sectors, 0, lpar,
229 &dev->tag)
230 : lv1_storage_read(dev->sbd.dev_id, region_id,
231 start_sector, sectors, 0, lpar,
232 &dev->tag);
233 if (res) {
234 dev_dbg(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
235 __LINE__, op, res);
236 return -1;
237 }
238
239 wait_for_completion(&dev->done);
240 if (dev->lv1_status) {
241 dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__,
242 __LINE__, op, dev->lv1_status);
243 return dev->lv1_status;
244 }
245
246 dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__, __LINE__,
247 op);
248
249 return 0;
250}
251EXPORT_SYMBOL_GPL(ps3stor_read_write_sectors);
252
253
254/**
255 * ps3stor_send_command - send a device command to a storage device
256 * @dev: Pointer to a struct ps3_storage_device
257 * @cmd: Command number
258 * @arg1: First command argument
259 * @arg2: Second command argument
260 * @arg3: Third command argument
261 * @arg4: Fourth command argument
262 *
263 * Returns 0 for success, -1 in case of failure to submit the command, or
264 * an LV1 status value in case of other errors
265 */
266u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd, u64 arg1,
267 u64 arg2, u64 arg3, u64 arg4)
268{
269 int res;
270
271 dev_dbg(&dev->sbd.core, "%s:%u: send device command 0x%lx\n", __func__,
272 __LINE__, cmd);
273
274 init_completion(&dev->done);
275
276 res = lv1_storage_send_device_command(dev->sbd.dev_id, cmd, arg1,
277 arg2, arg3, arg4, &dev->tag);
278 if (res) {
279 dev_err(&dev->sbd.core,
280 "%s:%u: send_device_command 0x%lx failed %d\n",
281 __func__, __LINE__, cmd, res);
282 return -1;
283 }
284
285 wait_for_completion(&dev->done);
286 if (dev->lv1_status) {
287 dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx failed 0x%lx\n",
288 __func__, __LINE__, cmd, dev->lv1_status);
289 return dev->lv1_status;
290 }
291
292 dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx completed\n", __func__,
293 __LINE__, cmd);
294
295 return 0;
296}
297EXPORT_SYMBOL_GPL(ps3stor_send_command);
298
299
300MODULE_LICENSE("GPL");
301MODULE_DESCRIPTION("PS3 Storage Bus Library");
302MODULE_AUTHOR("Sony Corporation");
diff --git a/drivers/ps3/sys-manager-core.c b/drivers/ps3/sys-manager-core.c
new file mode 100644
index 000000000000..31648f7d9ae1
--- /dev/null
+++ b/drivers/ps3/sys-manager-core.c
@@ -0,0 +1,68 @@
1/*
2 * PS3 System Manager core.
3 *
4 * Copyright (C) 2007 Sony Computer Entertainment Inc.
5 * Copyright 2007 Sony Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/kernel.h>
22#include <asm/ps3.h>
23
24/**
25 * Staticly linked routines that allow late binding of a loaded sys-manager
26 * module.
27 */
28
29static struct ps3_sys_manager_ops ps3_sys_manager_ops;
30
31/**
32 * ps3_register_sys_manager_ops - Bind ps3_sys_manager_ops to a module.
33 * @ops: struct ps3_sys_manager_ops.
34 *
35 * To be called from ps3_sys_manager_probe() and ps3_sys_manager_remove() to
36 * register call back ops for power control. Copies data to the static
37 * variable ps3_sys_manager_ops.
38 */
39
40void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops)
41{
42 BUG_ON(!ops);
43 BUG_ON(!ops->dev);
44 ps3_sys_manager_ops = ops ? *ops : ps3_sys_manager_ops;
45}
46EXPORT_SYMBOL_GPL(ps3_sys_manager_register_ops);
47
48void ps3_sys_manager_power_off(void)
49{
50 if (ps3_sys_manager_ops.power_off)
51 ps3_sys_manager_ops.power_off(ps3_sys_manager_ops.dev);
52
53 printk(KERN_EMERG "System Halted, OK to turn off power\n");
54 local_irq_disable();
55 while (1)
56 (void)0;
57}
58
59void ps3_sys_manager_restart(void)
60{
61 if (ps3_sys_manager_ops.restart)
62 ps3_sys_manager_ops.restart(ps3_sys_manager_ops.dev);
63
64 printk(KERN_EMERG "System Halted, OK to turn off power\n");
65 local_irq_disable();
66 while (1)
67 (void)0;
68}
diff --git a/drivers/ps3/sys-manager.c b/drivers/ps3/sys-manager.c
index 3aa2b0dcc369..8461b08ab9fb 100644
--- a/drivers/ps3/sys-manager.c
+++ b/drivers/ps3/sys-manager.c
@@ -35,7 +35,7 @@ MODULE_DESCRIPTION("PS3 System Manager");
35/** 35/**
36 * ps3_sys_manager - PS3 system manager driver. 36 * ps3_sys_manager - PS3 system manager driver.
37 * 37 *
38 * The system manager provides an asyncronous system event notification 38 * The system manager provides an asynchronous system event notification
39 * mechanism for reporting events like thermal alert and button presses to 39 * mechanism for reporting events like thermal alert and button presses to
40 * guests. It also provides support to control system shutdown and startup. 40 * guests. It also provides support to control system shutdown and startup.
41 * 41 *
@@ -52,6 +52,7 @@ MODULE_DESCRIPTION("PS3 System Manager");
52 * @size: Header size in bytes, curently 16. 52 * @size: Header size in bytes, curently 16.
53 * @payload_size: Message payload size in bytes. 53 * @payload_size: Message payload size in bytes.
54 * @service_id: Message type, one of enum ps3_sys_manager_service_id. 54 * @service_id: Message type, one of enum ps3_sys_manager_service_id.
55 * @request_tag: Unique number to identify reply.
55 */ 56 */
56 57
57struct ps3_sys_manager_header { 58struct ps3_sys_manager_header {
@@ -61,29 +62,49 @@ struct ps3_sys_manager_header {
61 u16 reserved_1; 62 u16 reserved_1;
62 u32 payload_size; 63 u32 payload_size;
63 u16 service_id; 64 u16 service_id;
64 u16 reserved_2[3]; 65 u16 reserved_2;
66 u32 request_tag;
65}; 67};
66 68
69#define dump_sm_header(_h) _dump_sm_header(_h, __func__, __LINE__)
70static void __maybe_unused _dump_sm_header(
71 const struct ps3_sys_manager_header *h, const char *func, int line)
72{
73 pr_debug("%s:%d: version: %xh\n", func, line, h->version);
74 pr_debug("%s:%d: size: %xh\n", func, line, h->size);
75 pr_debug("%s:%d: payload_size: %xh\n", func, line, h->payload_size);
76 pr_debug("%s:%d: service_id: %xh\n", func, line, h->service_id);
77 pr_debug("%s:%d: request_tag: %xh\n", func, line, h->request_tag);
78}
79
67/** 80/**
68 * @PS3_SM_RX_MSG_LEN - System manager received message length. 81 * @PS3_SM_RX_MSG_LEN_MIN - Shortest received message length.
82 * @PS3_SM_RX_MSG_LEN_MAX - Longest received message length.
69 * 83 *
70 * Currently all messages received from the system manager are the same length 84 * Currently all messages received from the system manager are either
71 * (16 bytes header + 16 bytes payload = 32 bytes). This knowlege is used to 85 * (16 bytes header + 8 bytes payload = 24 bytes) or (16 bytes header
72 * simplify the logic. 86 * + 16 bytes payload = 32 bytes). This knowlege is used to simplify
87 * the logic.
73 */ 88 */
74 89
75enum { 90enum {
76 PS3_SM_RX_MSG_LEN = 32, 91 PS3_SM_RX_MSG_LEN_MIN = 24,
92 PS3_SM_RX_MSG_LEN_MAX = 32,
77}; 93};
78 94
79/** 95/**
80 * enum ps3_sys_manager_service_id - Message header service_id. 96 * enum ps3_sys_manager_service_id - Message header service_id.
81 * @PS3_SM_SERVICE_ID_REQUEST: guest --> sys_manager. 97 * @PS3_SM_SERVICE_ID_REQUEST: guest --> sys_manager.
82 * @PS3_SM_SERVICE_ID_COMMAND: guest <-- sys_manager. 98 * @PS3_SM_SERVICE_ID_REQUEST_ERROR: guest <-- sys_manager.
83 * @PS3_SM_SERVICE_ID_RESPONSE: guest --> sys_manager. 99 * @PS3_SM_SERVICE_ID_COMMAND: guest <-- sys_manager.
84 * @PS3_SM_SERVICE_ID_SET_ATTR: guest --> sys_manager. 100 * @PS3_SM_SERVICE_ID_RESPONSE: guest --> sys_manager.
85 * @PS3_SM_SERVICE_ID_EXTERN_EVENT: guest <-- sys_manager. 101 * @PS3_SM_SERVICE_ID_SET_ATTR: guest --> sys_manager.
86 * @PS3_SM_SERVICE_ID_SET_NEXT_OP: guest --> sys_manager. 102 * @PS3_SM_SERVICE_ID_EXTERN_EVENT: guest <-- sys_manager.
103 * @PS3_SM_SERVICE_ID_SET_NEXT_OP: guest --> sys_manager.
104 *
105 * PS3_SM_SERVICE_ID_REQUEST_ERROR is returned for invalid data values in a
106 * a PS3_SM_SERVICE_ID_REQUEST message. It also seems to be returned when
107 * a REQUEST message is sent at the wrong time.
87 */ 108 */
88 109
89enum ps3_sys_manager_service_id { 110enum ps3_sys_manager_service_id {
@@ -93,6 +114,7 @@ enum ps3_sys_manager_service_id {
93 PS3_SM_SERVICE_ID_COMMAND = 3, 114 PS3_SM_SERVICE_ID_COMMAND = 3,
94 PS3_SM_SERVICE_ID_EXTERN_EVENT = 4, 115 PS3_SM_SERVICE_ID_EXTERN_EVENT = 4,
95 PS3_SM_SERVICE_ID_SET_NEXT_OP = 5, 116 PS3_SM_SERVICE_ID_SET_NEXT_OP = 5,
117 PS3_SM_SERVICE_ID_REQUEST_ERROR = 6,
96 PS3_SM_SERVICE_ID_SET_ATTR = 8, 118 PS3_SM_SERVICE_ID_SET_ATTR = 8,
97}; 119};
98 120
@@ -185,11 +207,21 @@ enum ps3_sys_manager_cmd {
185}; 207};
186 208
187/** 209/**
210 * ps3_sm_force_power_off - Poweroff helper.
211 *
212 * A global variable used to force a poweroff when the power button has
213 * been pressed irrespective of how init handles the ctrl_alt_del signal.
214 *
215 */
216
217static unsigned int ps3_sm_force_power_off;
218
219/**
188 * ps3_sys_manager_write - Helper to write a two part message to the vuart. 220 * ps3_sys_manager_write - Helper to write a two part message to the vuart.
189 * 221 *
190 */ 222 */
191 223
192static int ps3_sys_manager_write(struct ps3_vuart_port_device *dev, 224static int ps3_sys_manager_write(struct ps3_system_bus_device *dev,
193 const struct ps3_sys_manager_header *header, const void *payload) 225 const struct ps3_sys_manager_header *header, const void *payload)
194{ 226{
195 int result; 227 int result;
@@ -213,15 +245,10 @@ static int ps3_sys_manager_write(struct ps3_vuart_port_device *dev,
213 * 245 *
214 */ 246 */
215 247
216static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev, 248static int ps3_sys_manager_send_attr(struct ps3_system_bus_device *dev,
217 enum ps3_sys_manager_attr attr) 249 enum ps3_sys_manager_attr attr)
218{ 250{
219 static const struct ps3_sys_manager_header header = { 251 struct ps3_sys_manager_header header;
220 .version = 1,
221 .size = 16,
222 .payload_size = 16,
223 .service_id = PS3_SM_SERVICE_ID_SET_ATTR,
224 };
225 struct { 252 struct {
226 u8 version; 253 u8 version;
227 u8 reserved_1[3]; 254 u8 reserved_1[3];
@@ -232,6 +259,12 @@ static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev,
232 259
233 dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, attr); 260 dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, attr);
234 261
262 memset(&header, 0, sizeof(header));
263 header.version = 1;
264 header.size = 16;
265 header.payload_size = 16;
266 header.service_id = PS3_SM_SERVICE_ID_SET_ATTR;
267
235 memset(&payload, 0, sizeof(payload)); 268 memset(&payload, 0, sizeof(payload));
236 payload.version = 1; 269 payload.version = 1;
237 payload.attribute = attr; 270 payload.attribute = attr;
@@ -245,16 +278,11 @@ static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev,
245 * Tell the system manager what to do after this lpar is destroyed. 278 * Tell the system manager what to do after this lpar is destroyed.
246 */ 279 */
247 280
248static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev, 281static int ps3_sys_manager_send_next_op(struct ps3_system_bus_device *dev,
249 enum ps3_sys_manager_next_op op, 282 enum ps3_sys_manager_next_op op,
250 enum ps3_sys_manager_wake_source wake_source) 283 enum ps3_sys_manager_wake_source wake_source)
251{ 284{
252 static const struct ps3_sys_manager_header header = { 285 struct ps3_sys_manager_header header;
253 .version = 1,
254 .size = 16,
255 .payload_size = 16,
256 .service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP,
257 };
258 struct { 286 struct {
259 u8 version; 287 u8 version;
260 u8 type; 288 u8 type;
@@ -268,6 +296,12 @@ static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev,
268 296
269 dev_dbg(&dev->core, "%s:%d: (%xh)\n", __func__, __LINE__, op); 297 dev_dbg(&dev->core, "%s:%d: (%xh)\n", __func__, __LINE__, op);
270 298
299 memset(&header, 0, sizeof(header));
300 header.version = 1;
301 header.size = 16;
302 header.payload_size = 16;
303 header.service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP;
304
271 memset(&payload, 0, sizeof(payload)); 305 memset(&payload, 0, sizeof(payload));
272 payload.version = 3; 306 payload.version = 3;
273 payload.type = op; 307 payload.type = op;
@@ -286,32 +320,35 @@ static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev,
286 * the command is then communicated back to the system manager with a response 320 * the command is then communicated back to the system manager with a response
287 * message. 321 * message.
288 * 322 *
289 * Currently, the only supported request it the 'shutdown self' request. 323 * Currently, the only supported request is the 'shutdown self' request.
290 */ 324 */
291 325
292static int ps3_sys_manager_send_request_shutdown(struct ps3_vuart_port_device *dev) 326static int ps3_sys_manager_send_request_shutdown(
327 struct ps3_system_bus_device *dev)
293{ 328{
294 static const struct ps3_sys_manager_header header = { 329 struct ps3_sys_manager_header header;
295 .version = 1,
296 .size = 16,
297 .payload_size = 16,
298 .service_id = PS3_SM_SERVICE_ID_REQUEST,
299 };
300 struct { 330 struct {
301 u8 version; 331 u8 version;
302 u8 type; 332 u8 type;
303 u8 gos_id; 333 u8 gos_id;
304 u8 reserved_1[13]; 334 u8 reserved_1[13];
305 } static const payload = { 335 } payload;
306 .version = 1,
307 .type = 1, /* shutdown */
308 .gos_id = 0, /* self */
309 };
310 336
311 BUILD_BUG_ON(sizeof(payload) != 16); 337 BUILD_BUG_ON(sizeof(payload) != 16);
312 338
313 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); 339 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
314 340
341 memset(&header, 0, sizeof(header));
342 header.version = 1;
343 header.size = 16;
344 header.payload_size = 16;
345 header.service_id = PS3_SM_SERVICE_ID_REQUEST;
346
347 memset(&payload, 0, sizeof(payload));
348 payload.version = 1;
349 payload.type = 1; /* shutdown */
350 payload.gos_id = 0; /* self */
351
315 return ps3_sys_manager_write(dev, &header, &payload); 352 return ps3_sys_manager_write(dev, &header, &payload);
316} 353}
317 354
@@ -323,15 +360,10 @@ static int ps3_sys_manager_send_request_shutdown(struct ps3_vuart_port_device *d
323 * failure of a command sent by the system manager. 360 * failure of a command sent by the system manager.
324 */ 361 */
325 362
326static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev, 363static int ps3_sys_manager_send_response(struct ps3_system_bus_device *dev,
327 u64 status) 364 u64 status)
328{ 365{
329 static const struct ps3_sys_manager_header header = { 366 struct ps3_sys_manager_header header;
330 .version = 1,
331 .size = 16,
332 .payload_size = 16,
333 .service_id = PS3_SM_SERVICE_ID_RESPONSE,
334 };
335 struct { 367 struct {
336 u8 version; 368 u8 version;
337 u8 reserved_1[3]; 369 u8 reserved_1[3];
@@ -344,6 +376,12 @@ static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev,
344 dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__, 376 dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
345 (status ? "nak" : "ack")); 377 (status ? "nak" : "ack"));
346 378
379 memset(&header, 0, sizeof(header));
380 header.version = 1;
381 header.size = 16;
382 header.payload_size = 16;
383 header.service_id = PS3_SM_SERVICE_ID_RESPONSE;
384
347 memset(&payload, 0, sizeof(payload)); 385 memset(&payload, 0, sizeof(payload));
348 payload.version = 1; 386 payload.version = 1;
349 payload.status = status; 387 payload.status = status;
@@ -356,7 +394,7 @@ static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev,
356 * 394 *
357 */ 395 */
358 396
359static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev) 397static int ps3_sys_manager_handle_event(struct ps3_system_bus_device *dev)
360{ 398{
361 int result; 399 int result;
362 struct { 400 struct {
@@ -370,7 +408,7 @@ static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev)
370 BUILD_BUG_ON(sizeof(event) != 16); 408 BUILD_BUG_ON(sizeof(event) != 16);
371 409
372 result = ps3_vuart_read(dev, &event, sizeof(event)); 410 result = ps3_vuart_read(dev, &event, sizeof(event));
373 BUG_ON(result); 411 BUG_ON(result && "need to retry here");
374 412
375 if (event.version != 1) { 413 if (event.version != 1) {
376 dev_dbg(&dev->core, "%s:%d: unsupported event version (%u)\n", 414 dev_dbg(&dev->core, "%s:%d: unsupported event version (%u)\n",
@@ -382,11 +420,34 @@ static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev)
382 case PS3_SM_EVENT_POWER_PRESSED: 420 case PS3_SM_EVENT_POWER_PRESSED:
383 dev_dbg(&dev->core, "%s:%d: POWER_PRESSED\n", 421 dev_dbg(&dev->core, "%s:%d: POWER_PRESSED\n",
384 __func__, __LINE__); 422 __func__, __LINE__);
423 ps3_sm_force_power_off = 1;
424 /*
425 * A memory barrier is use here to sync memory since
426 * ps3_sys_manager_final_restart() could be called on
427 * another cpu.
428 */
429 wmb();
430 kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */
385 break; 431 break;
386 case PS3_SM_EVENT_POWER_RELEASED: 432 case PS3_SM_EVENT_POWER_RELEASED:
387 dev_dbg(&dev->core, "%s:%d: POWER_RELEASED (%u ms)\n", 433 dev_dbg(&dev->core, "%s:%d: POWER_RELEASED (%u ms)\n",
388 __func__, __LINE__, event.value); 434 __func__, __LINE__, event.value);
389 kill_cad_pid(SIGINT, 1); 435 break;
436 case PS3_SM_EVENT_RESET_PRESSED:
437 dev_dbg(&dev->core, "%s:%d: RESET_PRESSED\n",
438 __func__, __LINE__);
439 ps3_sm_force_power_off = 0;
440 /*
441 * A memory barrier is use here to sync memory since
442 * ps3_sys_manager_final_restart() could be called on
443 * another cpu.
444 */
445 wmb();
446 kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */
447 break;
448 case PS3_SM_EVENT_RESET_RELEASED:
449 dev_dbg(&dev->core, "%s:%d: RESET_RELEASED (%u ms)\n",
450 __func__, __LINE__, event.value);
390 break; 451 break;
391 case PS3_SM_EVENT_THERMAL_ALERT: 452 case PS3_SM_EVENT_THERMAL_ALERT:
392 dev_dbg(&dev->core, "%s:%d: THERMAL_ALERT (zone %u)\n", 453 dev_dbg(&dev->core, "%s:%d: THERMAL_ALERT (zone %u)\n",
@@ -411,7 +472,7 @@ static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev)
411 * The system manager sends this in reply to a 'request' message from the guest. 472 * The system manager sends this in reply to a 'request' message from the guest.
412 */ 473 */
413 474
414static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev) 475static int ps3_sys_manager_handle_cmd(struct ps3_system_bus_device *dev)
415{ 476{
416 int result; 477 int result;
417 struct { 478 struct {
@@ -425,6 +486,7 @@ static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev)
425 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); 486 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
426 487
427 result = ps3_vuart_read(dev, &cmd, sizeof(cmd)); 488 result = ps3_vuart_read(dev, &cmd, sizeof(cmd));
489 BUG_ON(result && "need to retry here");
428 490
429 if(result) 491 if(result)
430 return result; 492 return result;
@@ -448,9 +510,10 @@ static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev)
448/** 510/**
449 * ps3_sys_manager_handle_msg - First stage msg handler. 511 * ps3_sys_manager_handle_msg - First stage msg handler.
450 * 512 *
513 * Can be called directly to manually poll vuart and pump message handler.
451 */ 514 */
452 515
453static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev) 516static int ps3_sys_manager_handle_msg(struct ps3_system_bus_device *dev)
454{ 517{
455 int result; 518 int result;
456 struct ps3_sys_manager_header header; 519 struct ps3_sys_manager_header header;
@@ -464,12 +527,17 @@ static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev)
464 if (header.version != 1) { 527 if (header.version != 1) {
465 dev_dbg(&dev->core, "%s:%d: unsupported header version (%u)\n", 528 dev_dbg(&dev->core, "%s:%d: unsupported header version (%u)\n",
466 __func__, __LINE__, header.version); 529 __func__, __LINE__, header.version);
530 dump_sm_header(&header);
467 goto fail_header; 531 goto fail_header;
468 } 532 }
469 533
470 BUILD_BUG_ON(sizeof(header) != 16); 534 BUILD_BUG_ON(sizeof(header) != 16);
471 BUG_ON(header.size != 16); 535
472 BUG_ON(header.payload_size != 16); 536 if (header.size != 16 || (header.payload_size != 8
537 && header.payload_size != 16)) {
538 dump_sm_header(&header);
539 BUG();
540 }
473 541
474 switch (header.service_id) { 542 switch (header.service_id) {
475 case PS3_SM_SERVICE_ID_EXTERN_EVENT: 543 case PS3_SM_SERVICE_ID_EXTERN_EVENT:
@@ -478,6 +546,11 @@ static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev)
478 case PS3_SM_SERVICE_ID_COMMAND: 546 case PS3_SM_SERVICE_ID_COMMAND:
479 dev_dbg(&dev->core, "%s:%d: COMMAND\n", __func__, __LINE__); 547 dev_dbg(&dev->core, "%s:%d: COMMAND\n", __func__, __LINE__);
480 return ps3_sys_manager_handle_cmd(dev); 548 return ps3_sys_manager_handle_cmd(dev);
549 case PS3_SM_SERVICE_ID_REQUEST_ERROR:
550 dev_dbg(&dev->core, "%s:%d: REQUEST_ERROR\n", __func__,
551 __LINE__);
552 dump_sm_header(&header);
553 break;
481 default: 554 default:
482 dev_dbg(&dev->core, "%s:%d: unknown service_id (%u)\n", 555 dev_dbg(&dev->core, "%s:%d: unknown service_id (%u)\n",
483 __func__, __LINE__, header.service_id); 556 __func__, __LINE__, header.service_id);
@@ -494,45 +567,25 @@ fail_id:
494} 567}
495 568
496/** 569/**
497 * ps3_sys_manager_work - Asyncronous read handler. 570 * ps3_sys_manager_final_power_off - The final platform machine_power_off routine.
498 *
499 * Signaled when a complete message arrives at the vuart port.
500 */
501
502static void ps3_sys_manager_work(struct work_struct *work)
503{
504 struct ps3_vuart_port_device *dev = ps3_vuart_work_to_port_device(work);
505
506 ps3_sys_manager_handle_msg(dev);
507 ps3_vuart_read_async(dev, ps3_sys_manager_work, PS3_SM_RX_MSG_LEN);
508}
509
510struct {
511 struct ps3_vuart_port_device *dev;
512} static drv_priv;
513
514/**
515 * ps3_sys_manager_restart - The final platform machine_restart routine.
516 * 571 *
517 * This routine never returns. The routine disables asyncronous vuart reads 572 * This routine never returns. The routine disables asynchronous vuart reads
518 * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge 573 * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
519 * the shutdown command sent from the system manager. Soon after the 574 * the shutdown command sent from the system manager. Soon after the
520 * acknowledgement is sent the lpar is destroyed by the HV. This routine 575 * acknowledgement is sent the lpar is destroyed by the HV. This routine
521 * should only be called from ps3_restart(). 576 * should only be called from ps3_power_off() through
577 * ps3_sys_manager_ops.power_off.
522 */ 578 */
523 579
524void ps3_sys_manager_restart(void) 580static void ps3_sys_manager_final_power_off(struct ps3_system_bus_device *dev)
525{ 581{
526 struct ps3_vuart_port_device *dev = drv_priv.dev; 582 BUG_ON(!dev);
527
528 BUG_ON(!drv_priv.dev);
529 583
530 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); 584 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
531 585
532 ps3_vuart_cancel_async(dev); 586 ps3_vuart_cancel_async(dev);
533 587
534 ps3_sys_manager_send_attr(dev, 0); 588 ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN,
535 ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT,
536 PS3_SM_WAKE_DEFAULT); 589 PS3_SM_WAKE_DEFAULT);
537 ps3_sys_manager_send_request_shutdown(dev); 590 ps3_sys_manager_send_request_shutdown(dev);
538 591
@@ -543,26 +596,33 @@ void ps3_sys_manager_restart(void)
543} 596}
544 597
545/** 598/**
546 * ps3_sys_manager_power_off - The final platform machine_power_off routine. 599 * ps3_sys_manager_final_restart - The final platform machine_restart routine.
547 * 600 *
548 * This routine never returns. The routine disables asyncronous vuart reads 601 * This routine never returns. The routine disables asynchronous vuart reads
549 * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge 602 * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
550 * the shutdown command sent from the system manager. Soon after the 603 * the shutdown command sent from the system manager. Soon after the
551 * acknowledgement is sent the lpar is destroyed by the HV. This routine 604 * acknowledgement is sent the lpar is destroyed by the HV. This routine
552 * should only be called from ps3_power_off(). 605 * should only be called from ps3_restart() through ps3_sys_manager_ops.restart.
553 */ 606 */
554 607
555void ps3_sys_manager_power_off(void) 608static void ps3_sys_manager_final_restart(struct ps3_system_bus_device *dev)
556{ 609{
557 struct ps3_vuart_port_device *dev = drv_priv.dev; 610 BUG_ON(!dev);
558
559 BUG_ON(!drv_priv.dev);
560 611
561 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); 612 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
562 613
614 /* Check if we got here via a power button event. */
615
616 if (ps3_sm_force_power_off) {
617 dev_dbg(&dev->core, "%s:%d: forcing poweroff\n",
618 __func__, __LINE__);
619 ps3_sys_manager_final_power_off(dev);
620 }
621
563 ps3_vuart_cancel_async(dev); 622 ps3_vuart_cancel_async(dev);
564 623
565 ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN, 624 ps3_sys_manager_send_attr(dev, 0);
625 ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT,
566 PS3_SM_WAKE_DEFAULT); 626 PS3_SM_WAKE_DEFAULT);
567 ps3_sys_manager_send_request_shutdown(dev); 627 ps3_sys_manager_send_request_shutdown(dev);
568 628
@@ -572,31 +632,60 @@ void ps3_sys_manager_power_off(void)
572 ps3_sys_manager_handle_msg(dev); 632 ps3_sys_manager_handle_msg(dev);
573} 633}
574 634
575static int ps3_sys_manager_probe(struct ps3_vuart_port_device *dev) 635/**
636 * ps3_sys_manager_work - Asynchronous read handler.
637 *
638 * Signaled when PS3_SM_RX_MSG_LEN_MIN bytes arrive at the vuart port.
639 */
640
641static void ps3_sys_manager_work(struct ps3_system_bus_device *dev)
642{
643 ps3_sys_manager_handle_msg(dev);
644 ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN);
645}
646
647static int ps3_sys_manager_probe(struct ps3_system_bus_device *dev)
576{ 648{
577 int result; 649 int result;
650 struct ps3_sys_manager_ops ops;
578 651
579 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); 652 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
580 653
581 BUG_ON(drv_priv.dev); 654 ops.power_off = ps3_sys_manager_final_power_off;
582 drv_priv.dev = dev; 655 ops.restart = ps3_sys_manager_final_restart;
656 ops.dev = dev;
657
658 /* ps3_sys_manager_register_ops copies ops. */
659
660 ps3_sys_manager_register_ops(&ops);
583 661
584 result = ps3_sys_manager_send_attr(dev, PS3_SM_ATTR_ALL); 662 result = ps3_sys_manager_send_attr(dev, PS3_SM_ATTR_ALL);
585 BUG_ON(result); 663 BUG_ON(result);
586 664
587 result = ps3_vuart_read_async(dev, ps3_sys_manager_work, 665 result = ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN);
588 PS3_SM_RX_MSG_LEN);
589 BUG_ON(result); 666 BUG_ON(result);
590 667
591 return result; 668 return result;
592} 669}
593 670
671static int ps3_sys_manager_remove(struct ps3_system_bus_device *dev)
672{
673 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
674 return 0;
675}
676
677static void ps3_sys_manager_shutdown(struct ps3_system_bus_device *dev)
678{
679 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
680}
681
594static struct ps3_vuart_port_driver ps3_sys_manager = { 682static struct ps3_vuart_port_driver ps3_sys_manager = {
595 .match_id = PS3_MATCH_ID_SYSTEM_MANAGER, 683 .core.match_id = PS3_MATCH_ID_SYSTEM_MANAGER,
596 .core = { 684 .core.core.name = "ps3_sys_manager",
597 .name = "ps3_sys_manager",
598 },
599 .probe = ps3_sys_manager_probe, 685 .probe = ps3_sys_manager_probe,
686 .remove = ps3_sys_manager_remove,
687 .shutdown = ps3_sys_manager_shutdown,
688 .work = ps3_sys_manager_work,
600}; 689};
601 690
602static int __init ps3_sys_manager_init(void) 691static int __init ps3_sys_manager_init(void)
@@ -608,3 +697,6 @@ static int __init ps3_sys_manager_init(void)
608} 697}
609 698
610module_init(ps3_sys_manager_init); 699module_init(ps3_sys_manager_init);
700/* Module remove not supported. */
701
702MODULE_ALIAS(PS3_MODULE_ALIAS_SYSTEM_MANAGER);
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c
index ec2d36a1bc67..bea25a1391ee 100644
--- a/drivers/ps3/vuart.c
+++ b/drivers/ps3/vuart.c
@@ -71,6 +71,34 @@ enum vuart_interrupt_mask {
71}; 71};
72 72
73/** 73/**
74 * struct ps3_vuart_port_priv - private vuart device data.
75 */
76
77struct ps3_vuart_port_priv {
78 u64 interrupt_mask;
79
80 struct {
81 spinlock_t lock;
82 struct list_head head;
83 } tx_list;
84 struct {
85 struct ps3_vuart_work work;
86 unsigned long bytes_held;
87 spinlock_t lock;
88 struct list_head head;
89 } rx_list;
90 struct ps3_vuart_stats stats;
91};
92
93static struct ps3_vuart_port_priv *to_port_priv(
94 struct ps3_system_bus_device *dev)
95{
96 BUG_ON(!dev);
97 BUG_ON(!dev->driver_priv);
98 return (struct ps3_vuart_port_priv *)dev->driver_priv;
99}
100
101/**
74 * struct ports_bmp - bitmap indicating ports needing service. 102 * struct ports_bmp - bitmap indicating ports needing service.
75 * 103 *
76 * A 256 bit read only bitmap indicating ports needing service. Do not write 104 * A 256 bit read only bitmap indicating ports needing service. Do not write
@@ -83,31 +111,14 @@ struct ports_bmp {
83} __attribute__ ((aligned (32))); 111} __attribute__ ((aligned (32)));
84 112
85#define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__) 113#define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__)
86static void __attribute__ ((unused)) _dump_ports_bmp( 114static void __maybe_unused _dump_ports_bmp(
87 const struct ports_bmp* bmp, const char* func, int line) 115 const struct ports_bmp* bmp, const char* func, int line)
88{ 116{
89 pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status); 117 pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status);
90} 118}
91 119
92static int ps3_vuart_match_id_to_port(enum ps3_match_id match_id,
93 unsigned int *port_number)
94{
95 switch(match_id) {
96 case PS3_MATCH_ID_AV_SETTINGS:
97 *port_number = 0;
98 return 0;
99 case PS3_MATCH_ID_SYSTEM_MANAGER:
100 *port_number = 2;
101 return 0;
102 default:
103 WARN_ON(1);
104 *port_number = UINT_MAX;
105 return -EINVAL;
106 };
107}
108
109#define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__) 120#define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__)
110static void __attribute__ ((unused)) _dump_port_params(unsigned int port_number, 121static void __maybe_unused _dump_port_params(unsigned int port_number,
111 const char* func, int line) 122 const char* func, int line)
112{ 123{
113#if defined(DEBUG) 124#if defined(DEBUG)
@@ -144,14 +155,14 @@ struct vuart_triggers {
144 unsigned long tx; 155 unsigned long tx;
145}; 156};
146 157
147int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev, 158int ps3_vuart_get_triggers(struct ps3_system_bus_device *dev,
148 struct vuart_triggers *trig) 159 struct vuart_triggers *trig)
149{ 160{
150 int result; 161 int result;
151 unsigned long size; 162 unsigned long size;
152 unsigned long val; 163 unsigned long val;
153 164
154 result = lv1_get_virtual_uart_param(dev->priv->port_number, 165 result = lv1_get_virtual_uart_param(dev->port_number,
155 PARAM_TX_TRIGGER, &trig->tx); 166 PARAM_TX_TRIGGER, &trig->tx);
156 167
157 if (result) { 168 if (result) {
@@ -160,7 +171,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
160 return result; 171 return result;
161 } 172 }
162 173
163 result = lv1_get_virtual_uart_param(dev->priv->port_number, 174 result = lv1_get_virtual_uart_param(dev->port_number,
164 PARAM_RX_BUF_SIZE, &size); 175 PARAM_RX_BUF_SIZE, &size);
165 176
166 if (result) { 177 if (result) {
@@ -169,7 +180,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
169 return result; 180 return result;
170 } 181 }
171 182
172 result = lv1_get_virtual_uart_param(dev->priv->port_number, 183 result = lv1_get_virtual_uart_param(dev->port_number,
173 PARAM_RX_TRIGGER, &val); 184 PARAM_RX_TRIGGER, &val);
174 185
175 if (result) { 186 if (result) {
@@ -186,13 +197,13 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
186 return result; 197 return result;
187} 198}
188 199
189int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx, 200int ps3_vuart_set_triggers(struct ps3_system_bus_device *dev, unsigned int tx,
190 unsigned int rx) 201 unsigned int rx)
191{ 202{
192 int result; 203 int result;
193 unsigned long size; 204 unsigned long size;
194 205
195 result = lv1_set_virtual_uart_param(dev->priv->port_number, 206 result = lv1_set_virtual_uart_param(dev->port_number,
196 PARAM_TX_TRIGGER, tx); 207 PARAM_TX_TRIGGER, tx);
197 208
198 if (result) { 209 if (result) {
@@ -201,7 +212,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
201 return result; 212 return result;
202 } 213 }
203 214
204 result = lv1_get_virtual_uart_param(dev->priv->port_number, 215 result = lv1_get_virtual_uart_param(dev->port_number,
205 PARAM_RX_BUF_SIZE, &size); 216 PARAM_RX_BUF_SIZE, &size);
206 217
207 if (result) { 218 if (result) {
@@ -210,7 +221,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
210 return result; 221 return result;
211 } 222 }
212 223
213 result = lv1_set_virtual_uart_param(dev->priv->port_number, 224 result = lv1_set_virtual_uart_param(dev->port_number,
214 PARAM_RX_TRIGGER, size - rx); 225 PARAM_RX_TRIGGER, size - rx);
215 226
216 if (result) { 227 if (result) {
@@ -225,10 +236,12 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
225 return result; 236 return result;
226} 237}
227 238
228static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev, 239static int ps3_vuart_get_rx_bytes_waiting(struct ps3_system_bus_device *dev,
229 u64 *bytes_waiting) 240 u64 *bytes_waiting)
230{ 241{
231 int result = lv1_get_virtual_uart_param(dev->priv->port_number, 242 int result;
243
244 result = lv1_get_virtual_uart_param(dev->port_number,
232 PARAM_RX_BYTES, bytes_waiting); 245 PARAM_RX_BYTES, bytes_waiting);
233 246
234 if (result) 247 if (result)
@@ -240,17 +253,24 @@ static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev,
240 return result; 253 return result;
241} 254}
242 255
243static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev, 256/**
257 * ps3_vuart_set_interrupt_mask - Enable/disable the port interrupt sources.
258 * @dev: The struct ps3_system_bus_device instance.
259 * @bmp: Logical OR of enum vuart_interrupt_mask values. A zero bit disables.
260 */
261
262static int ps3_vuart_set_interrupt_mask(struct ps3_system_bus_device *dev,
244 unsigned long mask) 263 unsigned long mask)
245{ 264{
246 int result; 265 int result;
266 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
247 267
248 dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask); 268 dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask);
249 269
250 dev->priv->interrupt_mask = mask; 270 priv->interrupt_mask = mask;
251 271
252 result = lv1_set_virtual_uart_param(dev->priv->port_number, 272 result = lv1_set_virtual_uart_param(dev->port_number,
253 PARAM_INTERRUPT_MASK, dev->priv->interrupt_mask); 273 PARAM_INTERRUPT_MASK, priv->interrupt_mask);
254 274
255 if (result) 275 if (result)
256 dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n", 276 dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n",
@@ -259,79 +279,96 @@ static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev,
259 return result; 279 return result;
260} 280}
261 281
262static int ps3_vuart_get_interrupt_status(struct ps3_vuart_port_device *dev, 282static int ps3_vuart_get_interrupt_status(struct ps3_system_bus_device *dev,
263 unsigned long *status) 283 unsigned long *status)
264{ 284{
285 int result;
286 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
265 u64 tmp; 287 u64 tmp;
266 int result = lv1_get_virtual_uart_param(dev->priv->port_number, 288
289 result = lv1_get_virtual_uart_param(dev->port_number,
267 PARAM_INTERRUPT_STATUS, &tmp); 290 PARAM_INTERRUPT_STATUS, &tmp);
268 291
269 if (result) 292 if (result)
270 dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n", 293 dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n",
271 __func__, __LINE__, ps3_result(result)); 294 __func__, __LINE__, ps3_result(result));
272 295
273 *status = tmp & dev->priv->interrupt_mask; 296 *status = tmp & priv->interrupt_mask;
274 297
275 dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n", 298 dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n",
276 __func__, __LINE__, dev->priv->interrupt_mask, tmp, *status); 299 __func__, __LINE__, priv->interrupt_mask, tmp, *status);
277 300
278 return result; 301 return result;
279} 302}
280 303
281int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev) 304int ps3_vuart_enable_interrupt_tx(struct ps3_system_bus_device *dev)
282{ 305{
283 return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0 306 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
284 : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask 307
308 return (priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0
309 : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
285 | INTERRUPT_MASK_TX); 310 | INTERRUPT_MASK_TX);
286} 311}
287 312
288int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev) 313int ps3_vuart_enable_interrupt_rx(struct ps3_system_bus_device *dev)
289{ 314{
290 return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0 315 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
291 : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask 316
317 return (priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0
318 : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
292 | INTERRUPT_MASK_RX); 319 | INTERRUPT_MASK_RX);
293} 320}
294 321
295int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev) 322int ps3_vuart_enable_interrupt_disconnect(struct ps3_system_bus_device *dev)
296{ 323{
297 return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0 324 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
298 : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask 325
326 return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
327 : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
299 | INTERRUPT_MASK_DISCONNECT); 328 | INTERRUPT_MASK_DISCONNECT);
300} 329}
301 330
302int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev) 331int ps3_vuart_disable_interrupt_tx(struct ps3_system_bus_device *dev)
303{ 332{
304 return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX) 333 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
305 ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask 334
335 return (priv->interrupt_mask & INTERRUPT_MASK_TX)
336 ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
306 & ~INTERRUPT_MASK_TX) : 0; 337 & ~INTERRUPT_MASK_TX) : 0;
307} 338}
308 339
309int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev) 340int ps3_vuart_disable_interrupt_rx(struct ps3_system_bus_device *dev)
310{ 341{
311 return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX) 342 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
312 ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask 343
344 return (priv->interrupt_mask & INTERRUPT_MASK_RX)
345 ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
313 & ~INTERRUPT_MASK_RX) : 0; 346 & ~INTERRUPT_MASK_RX) : 0;
314} 347}
315 348
316int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev) 349int ps3_vuart_disable_interrupt_disconnect(struct ps3_system_bus_device *dev)
317{ 350{
318 return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) 351 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
319 ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask 352
353 return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
354 ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
320 & ~INTERRUPT_MASK_DISCONNECT) : 0; 355 & ~INTERRUPT_MASK_DISCONNECT) : 0;
321} 356}
322 357
323/** 358/**
324 * ps3_vuart_raw_write - Low level write helper. 359 * ps3_vuart_raw_write - Low level write helper.
360 * @dev: The struct ps3_system_bus_device instance.
325 * 361 *
326 * Do not call ps3_vuart_raw_write directly, use ps3_vuart_write. 362 * Do not call ps3_vuart_raw_write directly, use ps3_vuart_write.
327 */ 363 */
328 364
329static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev, 365static int ps3_vuart_raw_write(struct ps3_system_bus_device *dev,
330 const void* buf, unsigned int bytes, unsigned long *bytes_written) 366 const void* buf, unsigned int bytes, unsigned long *bytes_written)
331{ 367{
332 int result; 368 int result;
369 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
333 370
334 result = lv1_write_virtual_uart(dev->priv->port_number, 371 result = lv1_write_virtual_uart(dev->port_number,
335 ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written); 372 ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written);
336 373
337 if (result) { 374 if (result) {
@@ -340,28 +377,30 @@ static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev,
340 return result; 377 return result;
341 } 378 }
342 379
343 dev->priv->stats.bytes_written += *bytes_written; 380 priv->stats.bytes_written += *bytes_written;
344 381
345 dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, __LINE__, 382 dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, __LINE__,
346 *bytes_written, bytes, dev->priv->stats.bytes_written); 383 *bytes_written, bytes, priv->stats.bytes_written);
347 384
348 return result; 385 return result;
349} 386}
350 387
351/** 388/**
352 * ps3_vuart_raw_read - Low level read helper. 389 * ps3_vuart_raw_read - Low level read helper.
390 * @dev: The struct ps3_system_bus_device instance.
353 * 391 *
354 * Do not call ps3_vuart_raw_read directly, use ps3_vuart_read. 392 * Do not call ps3_vuart_raw_read directly, use ps3_vuart_read.
355 */ 393 */
356 394
357static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf, 395static int ps3_vuart_raw_read(struct ps3_system_bus_device *dev, void *buf,
358 unsigned int bytes, unsigned long *bytes_read) 396 unsigned int bytes, unsigned long *bytes_read)
359{ 397{
360 int result; 398 int result;
399 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
361 400
362 dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes); 401 dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
363 402
364 result = lv1_read_virtual_uart(dev->priv->port_number, 403 result = lv1_read_virtual_uart(dev->port_number,
365 ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read); 404 ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read);
366 405
367 if (result) { 406 if (result) {
@@ -370,25 +409,27 @@ static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf,
370 return result; 409 return result;
371 } 410 }
372 411
373 dev->priv->stats.bytes_read += *bytes_read; 412 priv->stats.bytes_read += *bytes_read;
374 413
375 dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__, 414 dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__,
376 *bytes_read, bytes, dev->priv->stats.bytes_read); 415 *bytes_read, bytes, priv->stats.bytes_read);
377 416
378 return result; 417 return result;
379} 418}
380 419
381/** 420/**
382 * ps3_vuart_clear_rx_bytes - Discard bytes received. 421 * ps3_vuart_clear_rx_bytes - Discard bytes received.
422 * @dev: The struct ps3_system_bus_device instance.
383 * @bytes: Max byte count to discard, zero = all pending. 423 * @bytes: Max byte count to discard, zero = all pending.
384 * 424 *
385 * Used to clear pending rx interrupt source. Will not block. 425 * Used to clear pending rx interrupt source. Will not block.
386 */ 426 */
387 427
388void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev, 428void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev,
389 unsigned int bytes) 429 unsigned int bytes)
390{ 430{
391 int result; 431 int result;
432 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
392 u64 bytes_waiting; 433 u64 bytes_waiting;
393 void* tmp; 434 void* tmp;
394 435
@@ -418,8 +459,9 @@ void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
418 459
419 /* Don't include these bytes in the stats. */ 460 /* Don't include these bytes in the stats. */
420 461
421 dev->priv->stats.bytes_read -= bytes_waiting; 462 priv->stats.bytes_read -= bytes_waiting;
422} 463}
464EXPORT_SYMBOL_GPL(ps3_vuart_clear_rx_bytes);
423 465
424/** 466/**
425 * struct list_buffer - An element for a port device fifo buffer list. 467 * struct list_buffer - An element for a port device fifo buffer list.
@@ -435,6 +477,7 @@ struct list_buffer {
435 477
436/** 478/**
437 * ps3_vuart_write - the entry point for writing data to a port 479 * ps3_vuart_write - the entry point for writing data to a port
480 * @dev: The struct ps3_system_bus_device instance.
438 * 481 *
439 * If the port is idle on entry as much of the incoming data is written to 482 * If the port is idle on entry as much of the incoming data is written to
440 * the port as the port will accept. Otherwise a list buffer is created 483 * the port as the port will accept. Otherwise a list buffer is created
@@ -442,25 +485,26 @@ struct list_buffer {
442 * then enqueued for transmision via the transmit interrupt. 485 * then enqueued for transmision via the transmit interrupt.
443 */ 486 */
444 487
445int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf, 488int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf,
446 unsigned int bytes) 489 unsigned int bytes)
447{ 490{
448 static unsigned long dbg_number; 491 static unsigned long dbg_number;
449 int result; 492 int result;
493 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
450 unsigned long flags; 494 unsigned long flags;
451 struct list_buffer *lb; 495 struct list_buffer *lb;
452 496
453 dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__, 497 dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
454 bytes, bytes); 498 bytes, bytes);
455 499
456 spin_lock_irqsave(&dev->priv->tx_list.lock, flags); 500 spin_lock_irqsave(&priv->tx_list.lock, flags);
457 501
458 if (list_empty(&dev->priv->tx_list.head)) { 502 if (list_empty(&priv->tx_list.head)) {
459 unsigned long bytes_written; 503 unsigned long bytes_written;
460 504
461 result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written); 505 result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written);
462 506
463 spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); 507 spin_unlock_irqrestore(&priv->tx_list.lock, flags);
464 508
465 if (result) { 509 if (result) {
466 dev_dbg(&dev->core, 510 dev_dbg(&dev->core,
@@ -478,7 +522,7 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
478 bytes -= bytes_written; 522 bytes -= bytes_written;
479 buf += bytes_written; 523 buf += bytes_written;
480 } else 524 } else
481 spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); 525 spin_unlock_irqrestore(&priv->tx_list.lock, flags);
482 526
483 lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL); 527 lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL);
484 528
@@ -491,29 +535,86 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
491 lb->tail = lb->data + bytes; 535 lb->tail = lb->data + bytes;
492 lb->dbg_number = ++dbg_number; 536 lb->dbg_number = ++dbg_number;
493 537
494 spin_lock_irqsave(&dev->priv->tx_list.lock, flags); 538 spin_lock_irqsave(&priv->tx_list.lock, flags);
495 list_add_tail(&lb->link, &dev->priv->tx_list.head); 539 list_add_tail(&lb->link, &priv->tx_list.head);
496 ps3_vuart_enable_interrupt_tx(dev); 540 ps3_vuart_enable_interrupt_tx(dev);
497 spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); 541 spin_unlock_irqrestore(&priv->tx_list.lock, flags);
498 542
499 dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n", 543 dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n",
500 __func__, __LINE__, lb->dbg_number, bytes); 544 __func__, __LINE__, lb->dbg_number, bytes);
501 545
502 return 0; 546 return 0;
503} 547}
548EXPORT_SYMBOL_GPL(ps3_vuart_write);
549
550/**
551 * ps3_vuart_queue_rx_bytes - Queue waiting bytes into the buffer list.
552 * @dev: The struct ps3_system_bus_device instance.
553 * @bytes_queued: Number of bytes queued to the buffer list.
554 *
555 * Must be called with priv->rx_list.lock held.
556 */
557
558static int ps3_vuart_queue_rx_bytes(struct ps3_system_bus_device *dev,
559 u64 *bytes_queued)
560{
561 static unsigned long dbg_number;
562 int result;
563 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
564 struct list_buffer *lb;
565 u64 bytes;
566
567 *bytes_queued = 0;
568
569 result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes);
570 BUG_ON(result);
571
572 if (result)
573 return -EIO;
574
575 if (!bytes)
576 return 0;
577
578 /* Add some extra space for recently arrived data. */
579
580 bytes += 128;
581
582 lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC);
583
584 if (!lb)
585 return -ENOMEM;
586
587 ps3_vuart_raw_read(dev, lb->data, bytes, &bytes);
588
589 lb->head = lb->data;
590 lb->tail = lb->data + bytes;
591 lb->dbg_number = ++dbg_number;
592
593 list_add_tail(&lb->link, &priv->rx_list.head);
594 priv->rx_list.bytes_held += bytes;
595
596 dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
597 __func__, __LINE__, lb->dbg_number, bytes);
598
599 *bytes_queued = bytes;
600
601 return 0;
602}
504 603
505/** 604/**
506 * ps3_vuart_read - the entry point for reading data from a port 605 * ps3_vuart_read - The entry point for reading data from a port.
507 * 606 *
508 * If enough bytes to satisfy the request are held in the buffer list those 607 * Queue data waiting at the port, and if enough bytes to satisfy the request
509 * bytes are dequeued and copied to the caller's buffer. Emptied list buffers 608 * are held in the buffer list those bytes are dequeued and copied to the
510 * are retiered. If the request cannot be statified by bytes held in the list 609 * caller's buffer. Emptied list buffers are retiered. If the request cannot
511 * buffers -EAGAIN is returned. 610 * be statified by bytes held in the list buffers -EAGAIN is returned.
512 */ 611 */
513 612
514int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf, 613int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf,
515 unsigned int bytes) 614 unsigned int bytes)
516{ 615{
616 int result;
617 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
517 unsigned long flags; 618 unsigned long flags;
518 struct list_buffer *lb, *n; 619 struct list_buffer *lb, *n;
519 unsigned long bytes_read; 620 unsigned long bytes_read;
@@ -521,30 +622,37 @@ int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
521 dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__, 622 dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
522 bytes, bytes); 623 bytes, bytes);
523 624
524 spin_lock_irqsave(&dev->priv->rx_list.lock, flags); 625 spin_lock_irqsave(&priv->rx_list.lock, flags);
525 626
526 if (dev->priv->rx_list.bytes_held < bytes) { 627 /* Queue rx bytes here for polled reads. */
527 spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags); 628
528 dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n", 629 while (priv->rx_list.bytes_held < bytes) {
529 __func__, __LINE__, 630 u64 tmp;
530 bytes - dev->priv->rx_list.bytes_held); 631
531 return -EAGAIN; 632 result = ps3_vuart_queue_rx_bytes(dev, &tmp);
633 if (result || !tmp) {
634 dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
635 __func__, __LINE__,
636 bytes - priv->rx_list.bytes_held);
637 spin_unlock_irqrestore(&priv->rx_list.lock, flags);
638 return -EAGAIN;
639 }
532 } 640 }
533 641
534 list_for_each_entry_safe(lb, n, &dev->priv->rx_list.head, link) { 642 list_for_each_entry_safe(lb, n, &priv->rx_list.head, link) {
535 bytes_read = min((unsigned int)(lb->tail - lb->head), bytes); 643 bytes_read = min((unsigned int)(lb->tail - lb->head), bytes);
536 644
537 memcpy(buf, lb->head, bytes_read); 645 memcpy(buf, lb->head, bytes_read);
538 buf += bytes_read; 646 buf += bytes_read;
539 bytes -= bytes_read; 647 bytes -= bytes_read;
540 dev->priv->rx_list.bytes_held -= bytes_read; 648 priv->rx_list.bytes_held -= bytes_read;
541 649
542 if (bytes_read < lb->tail - lb->head) { 650 if (bytes_read < lb->tail - lb->head) {
543 lb->head += bytes_read; 651 lb->head += bytes_read;
544 dev_dbg(&dev->core, "%s:%d: buf_%lu: dequeued %lxh " 652 dev_dbg(&dev->core, "%s:%d: buf_%lu: dequeued %lxh "
545 "bytes\n", __func__, __LINE__, lb->dbg_number, 653 "bytes\n", __func__, __LINE__, lb->dbg_number,
546 bytes_read); 654 bytes_read);
547 spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags); 655 spin_unlock_irqrestore(&priv->rx_list.lock, flags);
548 return 0; 656 return 0;
549 } 657 }
550 658
@@ -556,16 +664,32 @@ int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
556 kfree(lb); 664 kfree(lb);
557 } 665 }
558 666
559 spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags); 667 spin_unlock_irqrestore(&priv->rx_list.lock, flags);
560 return 0; 668 return 0;
561} 669}
670EXPORT_SYMBOL_GPL(ps3_vuart_read);
562 671
563int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func, 672/**
564 unsigned int bytes) 673 * ps3_vuart_work - Asynchronous read handler.
674 */
675
676static void ps3_vuart_work(struct work_struct *work)
677{
678 struct ps3_system_bus_device *dev =
679 ps3_vuart_work_to_system_bus_dev(work);
680 struct ps3_vuart_port_driver *drv =
681 ps3_system_bus_dev_to_vuart_drv(dev);
682
683 BUG_ON(!drv);
684 drv->work(dev);
685}
686
687int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes)
565{ 688{
689 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
566 unsigned long flags; 690 unsigned long flags;
567 691
568 if(dev->priv->work.trigger) { 692 if (priv->rx_list.work.trigger) {
569 dev_dbg(&dev->core, "%s:%d: warning, multiple calls\n", 693 dev_dbg(&dev->core, "%s:%d: warning, multiple calls\n",
570 __func__, __LINE__); 694 __func__, __LINE__);
571 return -EAGAIN; 695 return -EAGAIN;
@@ -573,30 +697,32 @@ int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
573 697
574 BUG_ON(!bytes); 698 BUG_ON(!bytes);
575 699
576 PREPARE_WORK(&dev->priv->work.work, func); 700 PREPARE_WORK(&priv->rx_list.work.work, ps3_vuart_work);
577 701
578 spin_lock_irqsave(&dev->priv->work.lock, flags); 702 spin_lock_irqsave(&priv->rx_list.lock, flags);
579 if(dev->priv->rx_list.bytes_held >= bytes) { 703 if (priv->rx_list.bytes_held >= bytes) {
580 dev_dbg(&dev->core, "%s:%d: schedule_work %xh bytes\n", 704 dev_dbg(&dev->core, "%s:%d: schedule_work %xh bytes\n",
581 __func__, __LINE__, bytes); 705 __func__, __LINE__, bytes);
582 schedule_work(&dev->priv->work.work); 706 schedule_work(&priv->rx_list.work.work);
583 spin_unlock_irqrestore(&dev->priv->work.lock, flags); 707 spin_unlock_irqrestore(&priv->rx_list.lock, flags);
584 return 0; 708 return 0;
585 } 709 }
586 710
587 dev->priv->work.trigger = bytes; 711 priv->rx_list.work.trigger = bytes;
588 spin_unlock_irqrestore(&dev->priv->work.lock, flags); 712 spin_unlock_irqrestore(&priv->rx_list.lock, flags);
589 713
590 dev_dbg(&dev->core, "%s:%d: waiting for %u(%xh) bytes\n", __func__, 714 dev_dbg(&dev->core, "%s:%d: waiting for %u(%xh) bytes\n", __func__,
591 __LINE__, bytes, bytes); 715 __LINE__, bytes, bytes);
592 716
593 return 0; 717 return 0;
594} 718}
719EXPORT_SYMBOL_GPL(ps3_vuart_read_async);
595 720
596void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev) 721void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev)
597{ 722{
598 dev->priv->work.trigger = 0; 723 to_port_priv(dev)->rx_list.work.trigger = 0;
599} 724}
725EXPORT_SYMBOL_GPL(ps3_vuart_cancel_async);
600 726
601/** 727/**
602 * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler 728 * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler
@@ -606,18 +732,19 @@ void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev)
606 * adjusts the final list buffer state for a partial write. 732 * adjusts the final list buffer state for a partial write.
607 */ 733 */
608 734
609static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev) 735static int ps3_vuart_handle_interrupt_tx(struct ps3_system_bus_device *dev)
610{ 736{
611 int result = 0; 737 int result = 0;
738 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
612 unsigned long flags; 739 unsigned long flags;
613 struct list_buffer *lb, *n; 740 struct list_buffer *lb, *n;
614 unsigned long bytes_total = 0; 741 unsigned long bytes_total = 0;
615 742
616 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); 743 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
617 744
618 spin_lock_irqsave(&dev->priv->tx_list.lock, flags); 745 spin_lock_irqsave(&priv->tx_list.lock, flags);
619 746
620 list_for_each_entry_safe(lb, n, &dev->priv->tx_list.head, link) { 747 list_for_each_entry_safe(lb, n, &priv->tx_list.head, link) {
621 748
622 unsigned long bytes_written; 749 unsigned long bytes_written;
623 750
@@ -651,7 +778,7 @@ static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev)
651 778
652 ps3_vuart_disable_interrupt_tx(dev); 779 ps3_vuart_disable_interrupt_tx(dev);
653port_full: 780port_full:
654 spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); 781 spin_unlock_irqrestore(&priv->tx_list.lock, flags);
655 dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n", 782 dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n",
656 __func__, __LINE__, bytes_total); 783 __func__, __LINE__, bytes_total);
657 return result; 784 return result;
@@ -665,60 +792,37 @@ port_full:
665 * buffer list. Buffer list data is dequeued via ps3_vuart_read. 792 * buffer list. Buffer list data is dequeued via ps3_vuart_read.
666 */ 793 */
667 794
668static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev) 795static int ps3_vuart_handle_interrupt_rx(struct ps3_system_bus_device *dev)
669{ 796{
670 static unsigned long dbg_number; 797 int result;
671 int result = 0; 798 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
672 unsigned long flags; 799 unsigned long flags;
673 struct list_buffer *lb; 800 u64 bytes;
674 unsigned long bytes;
675 801
676 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); 802 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
677 803
678 result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes); 804 spin_lock_irqsave(&priv->rx_list.lock, flags);
679 805 result = ps3_vuart_queue_rx_bytes(dev, &bytes);
680 if (result)
681 return -EIO;
682
683 BUG_ON(!bytes);
684
685 /* Add some extra space for recently arrived data. */
686
687 bytes += 128;
688
689 lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC);
690 806
691 if (!lb) 807 if (result) {
692 return -ENOMEM; 808 spin_unlock_irqrestore(&priv->rx_list.lock, flags);
693 809 return result;
694 ps3_vuart_raw_read(dev, lb->data, bytes, &bytes); 810 }
695
696 lb->head = lb->data;
697 lb->tail = lb->data + bytes;
698 lb->dbg_number = ++dbg_number;
699
700 spin_lock_irqsave(&dev->priv->rx_list.lock, flags);
701 list_add_tail(&lb->link, &dev->priv->rx_list.head);
702 dev->priv->rx_list.bytes_held += bytes;
703 spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
704
705 dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
706 __func__, __LINE__, lb->dbg_number, bytes);
707 811
708 spin_lock_irqsave(&dev->priv->work.lock, flags); 812 if (priv->rx_list.work.trigger && priv->rx_list.bytes_held
709 if(dev->priv->work.trigger 813 >= priv->rx_list.work.trigger) {
710 && dev->priv->rx_list.bytes_held >= dev->priv->work.trigger) {
711 dev_dbg(&dev->core, "%s:%d: schedule_work %lxh bytes\n", 814 dev_dbg(&dev->core, "%s:%d: schedule_work %lxh bytes\n",
712 __func__, __LINE__, dev->priv->work.trigger); 815 __func__, __LINE__, priv->rx_list.work.trigger);
713 dev->priv->work.trigger = 0; 816 priv->rx_list.work.trigger = 0;
714 schedule_work(&dev->priv->work.work); 817 schedule_work(&priv->rx_list.work.work);
715 } 818 }
716 spin_unlock_irqrestore(&dev->priv->work.lock, flags); 819
717 return 0; 820 spin_unlock_irqrestore(&priv->rx_list.lock, flags);
821 return result;
718} 822}
719 823
720static int ps3_vuart_handle_interrupt_disconnect( 824static int ps3_vuart_handle_interrupt_disconnect(
721 struct ps3_vuart_port_device *dev) 825 struct ps3_system_bus_device *dev)
722{ 826{
723 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); 827 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
724 BUG_ON("no support"); 828 BUG_ON("no support");
@@ -733,9 +837,10 @@ static int ps3_vuart_handle_interrupt_disconnect(
733 * stage handler after one iteration. 837 * stage handler after one iteration.
734 */ 838 */
735 839
736static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev) 840static int ps3_vuart_handle_port_interrupt(struct ps3_system_bus_device *dev)
737{ 841{
738 int result; 842 int result;
843 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
739 unsigned long status; 844 unsigned long status;
740 845
741 result = ps3_vuart_get_interrupt_status(dev, &status); 846 result = ps3_vuart_get_interrupt_status(dev, &status);
@@ -747,21 +852,21 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
747 status); 852 status);
748 853
749 if (status & INTERRUPT_MASK_DISCONNECT) { 854 if (status & INTERRUPT_MASK_DISCONNECT) {
750 dev->priv->stats.disconnect_interrupts++; 855 priv->stats.disconnect_interrupts++;
751 result = ps3_vuart_handle_interrupt_disconnect(dev); 856 result = ps3_vuart_handle_interrupt_disconnect(dev);
752 if (result) 857 if (result)
753 ps3_vuart_disable_interrupt_disconnect(dev); 858 ps3_vuart_disable_interrupt_disconnect(dev);
754 } 859 }
755 860
756 if (status & INTERRUPT_MASK_TX) { 861 if (status & INTERRUPT_MASK_TX) {
757 dev->priv->stats.tx_interrupts++; 862 priv->stats.tx_interrupts++;
758 result = ps3_vuart_handle_interrupt_tx(dev); 863 result = ps3_vuart_handle_interrupt_tx(dev);
759 if (result) 864 if (result)
760 ps3_vuart_disable_interrupt_tx(dev); 865 ps3_vuart_disable_interrupt_tx(dev);
761 } 866 }
762 867
763 if (status & INTERRUPT_MASK_RX) { 868 if (status & INTERRUPT_MASK_RX) {
764 dev->priv->stats.rx_interrupts++; 869 priv->stats.rx_interrupts++;
765 result = ps3_vuart_handle_interrupt_rx(dev); 870 result = ps3_vuart_handle_interrupt_rx(dev);
766 if (result) 871 if (result)
767 ps3_vuart_disable_interrupt_rx(dev); 872 ps3_vuart_disable_interrupt_rx(dev);
@@ -771,11 +876,11 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
771} 876}
772 877
773struct vuart_bus_priv { 878struct vuart_bus_priv {
774 const struct ports_bmp bmp; 879 struct ports_bmp *bmp;
775 unsigned int virq; 880 unsigned int virq;
776 struct semaphore probe_mutex; 881 struct semaphore probe_mutex;
777 int use_count; 882 int use_count;
778 struct ps3_vuart_port_device *devices[PORT_COUNT]; 883 struct ps3_system_bus_device *devices[PORT_COUNT];
779} static vuart_bus_priv; 884} static vuart_bus_priv;
780 885
781/** 886/**
@@ -788,17 +893,16 @@ struct vuart_bus_priv {
788 893
789static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private) 894static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private)
790{ 895{
791 struct vuart_bus_priv *bus_priv; 896 struct vuart_bus_priv *bus_priv = _private;
792 897
793 BUG_ON(!_private); 898 BUG_ON(!bus_priv);
794 bus_priv = (struct vuart_bus_priv *)_private;
795 899
796 while (1) { 900 while (1) {
797 unsigned int port; 901 unsigned int port;
798 902
799 dump_ports_bmp(&bus_priv->bmp); 903 dump_ports_bmp(bus_priv->bmp);
800 904
801 port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp.status); 905 port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp->status);
802 906
803 if (port == BITS_PER_LONG) 907 if (port == BITS_PER_LONG)
804 break; 908 break;
@@ -812,100 +916,144 @@ static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private)
812 return IRQ_HANDLED; 916 return IRQ_HANDLED;
813} 917}
814 918
815static int ps3_vuart_match(struct device *_dev, struct device_driver *_drv) 919static int ps3_vuart_bus_interrupt_get(void)
816{ 920{
817 int result; 921 int result;
818 struct ps3_vuart_port_driver *drv = to_ps3_vuart_port_driver(_drv);
819 struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
820 922
821 result = dev->match_id == drv->match_id; 923 pr_debug(" -> %s:%d\n", __func__, __LINE__);
924
925 vuart_bus_priv.use_count++;
926
927 BUG_ON(vuart_bus_priv.use_count > 2);
928
929 if (vuart_bus_priv.use_count != 1) {
930 return 0;
931 }
932
933 BUG_ON(vuart_bus_priv.bmp);
934
935 vuart_bus_priv.bmp = kzalloc(sizeof(struct ports_bmp), GFP_KERNEL);
936
937 if (!vuart_bus_priv.bmp) {
938 pr_debug("%s:%d: kzalloc failed.\n", __func__, __LINE__);
939 result = -ENOMEM;
940 goto fail_bmp_malloc;
941 }
942
943 result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY, vuart_bus_priv.bmp,
944 &vuart_bus_priv.virq);
945
946 if (result) {
947 pr_debug("%s:%d: ps3_vuart_irq_setup failed (%d)\n",
948 __func__, __LINE__, result);
949 result = -EPERM;
950 goto fail_alloc_irq;
951 }
952
953 result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
954 IRQF_DISABLED, "vuart", &vuart_bus_priv);
822 955
823 dev_info(&dev->core, "%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__, 956 if (result) {
824 __LINE__, dev->match_id, dev->core.bus_id, drv->match_id, 957 pr_debug("%s:%d: request_irq failed (%d)\n",
825 drv->core.name, (result ? "match" : "miss")); 958 __func__, __LINE__, result);
959 goto fail_request_irq;
960 }
826 961
962 pr_debug(" <- %s:%d: ok\n", __func__, __LINE__);
827 return result; 963 return result;
964
965fail_request_irq:
966 ps3_vuart_irq_destroy(vuart_bus_priv.virq);
967 vuart_bus_priv.virq = NO_IRQ;
968fail_alloc_irq:
969 kfree(vuart_bus_priv.bmp);
970 vuart_bus_priv.bmp = NULL;
971fail_bmp_malloc:
972 vuart_bus_priv.use_count--;
973 pr_debug(" <- %s:%d: failed\n", __func__, __LINE__);
974 return result;
975}
976
977static int ps3_vuart_bus_interrupt_put(void)
978{
979 pr_debug(" -> %s:%d\n", __func__, __LINE__);
980
981 vuart_bus_priv.use_count--;
982
983 BUG_ON(vuart_bus_priv.use_count < 0);
984
985 if (vuart_bus_priv.use_count != 0)
986 return 0;
987
988 free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
989
990 ps3_vuart_irq_destroy(vuart_bus_priv.virq);
991 vuart_bus_priv.virq = NO_IRQ;
992
993 kfree(vuart_bus_priv.bmp);
994 vuart_bus_priv.bmp = NULL;
995
996 pr_debug(" <- %s:%d\n", __func__, __LINE__);
997 return 0;
828} 998}
829 999
830static int ps3_vuart_probe(struct device *_dev) 1000static int ps3_vuart_probe(struct ps3_system_bus_device *dev)
831{ 1001{
832 int result; 1002 int result;
833 unsigned int port_number; 1003 struct ps3_vuart_port_driver *drv;
834 struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); 1004 struct ps3_vuart_port_priv *priv = NULL;
835 struct ps3_vuart_port_driver *drv =
836 to_ps3_vuart_port_driver(_dev->driver);
837 1005
838 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); 1006 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
839 1007
1008 drv = ps3_system_bus_dev_to_vuart_drv(dev);
1009
1010 dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
1011 drv->core.core.name);
1012
840 BUG_ON(!drv); 1013 BUG_ON(!drv);
841 1014
842 down(&vuart_bus_priv.probe_mutex); 1015 if (dev->port_number >= PORT_COUNT) {
1016 BUG();
1017 return -EINVAL;
1018 }
843 1019
844 /* Setup vuart_bus_priv.devices[]. */ 1020 down(&vuart_bus_priv.probe_mutex);
845 1021
846 result = ps3_vuart_match_id_to_port(dev->match_id, 1022 result = ps3_vuart_bus_interrupt_get();
847 &port_number);
848 1023
849 if (result) { 1024 if (result)
850 dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n", 1025 goto fail_setup_interrupt;
851 __func__, __LINE__, dev->match_id);
852 result = -EINVAL;
853 goto fail_match;
854 }
855 1026
856 if (vuart_bus_priv.devices[port_number]) { 1027 if (vuart_bus_priv.devices[dev->port_number]) {
857 dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__, 1028 dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__,
858 __LINE__, port_number); 1029 __LINE__, dev->port_number);
859 result = -EBUSY; 1030 result = -EBUSY;
860 goto fail_match; 1031 goto fail_busy;
861 } 1032 }
862 1033
863 vuart_bus_priv.devices[port_number] = dev; 1034 vuart_bus_priv.devices[dev->port_number] = dev;
864 1035
865 /* Setup dev->priv. */ 1036 /* Setup dev->driver_priv. */
866 1037
867 dev->priv = kzalloc(sizeof(struct ps3_vuart_port_priv), GFP_KERNEL); 1038 dev->driver_priv = kzalloc(sizeof(struct ps3_vuart_port_priv),
1039 GFP_KERNEL);
868 1040
869 if (!dev->priv) { 1041 if (!dev->driver_priv) {
870 result = -ENOMEM; 1042 result = -ENOMEM;
871 goto fail_alloc; 1043 goto fail_dev_malloc;
872 } 1044 }
873 1045
874 dev->priv->port_number = port_number; 1046 priv = to_port_priv(dev);
875
876 INIT_LIST_HEAD(&dev->priv->tx_list.head);
877 spin_lock_init(&dev->priv->tx_list.lock);
878 1047
879 INIT_LIST_HEAD(&dev->priv->rx_list.head); 1048 INIT_LIST_HEAD(&priv->tx_list.head);
880 spin_lock_init(&dev->priv->rx_list.lock); 1049 spin_lock_init(&priv->tx_list.lock);
881 1050
882 INIT_WORK(&dev->priv->work.work, NULL); 1051 INIT_LIST_HEAD(&priv->rx_list.head);
883 spin_lock_init(&dev->priv->work.lock); 1052 spin_lock_init(&priv->rx_list.lock);
884 dev->priv->work.trigger = 0;
885 dev->priv->work.dev = dev;
886 1053
887 if (++vuart_bus_priv.use_count == 1) { 1054 INIT_WORK(&priv->rx_list.work.work, NULL);
888 1055 priv->rx_list.work.trigger = 0;
889 result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY, 1056 priv->rx_list.work.dev = dev;
890 (void*)&vuart_bus_priv.bmp.status, &vuart_bus_priv.virq);
891
892 if (result) {
893 dev_dbg(&dev->core,
894 "%s:%d: ps3_vuart_irq_setup failed (%d)\n",
895 __func__, __LINE__, result);
896 result = -EPERM;
897 goto fail_alloc_irq;
898 }
899
900 result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
901 IRQF_DISABLED, "vuart", &vuart_bus_priv);
902
903 if (result) {
904 dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n",
905 __func__, __LINE__, result);
906 goto fail_request_irq;
907 }
908 }
909 1057
910 /* clear stale pending interrupts */ 1058 /* clear stale pending interrupts */
911 1059
@@ -936,150 +1084,158 @@ static int ps3_vuart_probe(struct device *_dev)
936 1084
937fail_probe: 1085fail_probe:
938 ps3_vuart_set_interrupt_mask(dev, 0); 1086 ps3_vuart_set_interrupt_mask(dev, 0);
939fail_request_irq: 1087 kfree(dev->driver_priv);
940 ps3_vuart_irq_destroy(vuart_bus_priv.virq); 1088 dev->driver_priv = NULL;
941 vuart_bus_priv.virq = NO_IRQ; 1089fail_dev_malloc:
942fail_alloc_irq: 1090 vuart_bus_priv.devices[dev->port_number] = NULL;
943 --vuart_bus_priv.use_count; 1091fail_busy:
944 kfree(dev->priv); 1092 ps3_vuart_bus_interrupt_put();
945 dev->priv = NULL; 1093fail_setup_interrupt:
946fail_alloc:
947 vuart_bus_priv.devices[port_number] = NULL;
948fail_match:
949 up(&vuart_bus_priv.probe_mutex); 1094 up(&vuart_bus_priv.probe_mutex);
950 dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__); 1095 dev_dbg(&dev->core, "%s:%d: failed\n", __func__, __LINE__);
951 return result; 1096 return result;
952} 1097}
953 1098
954static int ps3_vuart_remove(struct device *_dev) 1099/**
1100 * ps3_vuart_cleanup - common cleanup helper.
1101 * @dev: The struct ps3_system_bus_device instance.
1102 *
1103 * Cleans interrupts and HV resources. Must be called with
1104 * vuart_bus_priv.probe_mutex held. Used by ps3_vuart_remove and
1105 * ps3_vuart_shutdown. After this call, polled reading will still work.
1106 */
1107
1108static int ps3_vuart_cleanup(struct ps3_system_bus_device *dev)
955{ 1109{
956 struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); 1110 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
957 struct ps3_vuart_port_driver *drv = 1111
958 to_ps3_vuart_port_driver(_dev->driver); 1112 ps3_vuart_cancel_async(dev);
1113 ps3_vuart_set_interrupt_mask(dev, 0);
1114 ps3_vuart_bus_interrupt_put();
1115 return 0;
1116}
1117
1118/**
1119 * ps3_vuart_remove - Completely clean the device instance.
1120 * @dev: The struct ps3_system_bus_device instance.
1121 *
1122 * Cleans all memory, interrupts and HV resources. After this call the
1123 * device can no longer be used.
1124 */
1125
1126static int ps3_vuart_remove(struct ps3_system_bus_device *dev)
1127{
1128 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
1129 struct ps3_vuart_port_driver *drv;
1130
1131 BUG_ON(!dev);
959 1132
960 down(&vuart_bus_priv.probe_mutex); 1133 down(&vuart_bus_priv.probe_mutex);
961 1134
962 dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__, 1135 dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
963 dev->core.bus_id); 1136 dev->match_id);
964 1137
965 BUG_ON(vuart_bus_priv.use_count < 1); 1138 if (!dev->core.driver) {
1139 dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
1140 __LINE__);
1141 up(&vuart_bus_priv.probe_mutex);
1142 return 0;
1143 }
966 1144
967 if (drv->remove) 1145 drv = ps3_system_bus_dev_to_vuart_drv(dev);
968 drv->remove(dev);
969 else
970 dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__,
971 __LINE__, dev->core.bus_id);
972 1146
973 vuart_bus_priv.devices[dev->priv->port_number] = NULL; 1147 BUG_ON(!drv);
974 1148
975 if (--vuart_bus_priv.use_count == 0) { 1149 if (drv->remove) {
1150 drv->remove(dev);
1151 } else {
1152 dev_dbg(&dev->core, "%s:%d: no remove method\n", __func__,
1153 __LINE__);
976 BUG(); 1154 BUG();
977 free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
978 ps3_vuart_irq_destroy(vuart_bus_priv.virq);
979 vuart_bus_priv.virq = NO_IRQ;
980 } 1155 }
981 1156
982 kfree(dev->priv); 1157 ps3_vuart_cleanup(dev);
983 dev->priv = NULL; 1158
1159 vuart_bus_priv.devices[dev->port_number] = NULL;
1160 kfree(priv);
1161 priv = NULL;
984 1162
1163 dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
985 up(&vuart_bus_priv.probe_mutex); 1164 up(&vuart_bus_priv.probe_mutex);
986 return 0; 1165 return 0;
987} 1166}
988 1167
989static void ps3_vuart_shutdown(struct device *_dev)
990{
991 struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
992 struct ps3_vuart_port_driver *drv =
993 to_ps3_vuart_port_driver(_dev->driver);
994
995 dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
996 dev->core.bus_id);
997
998 if (drv->shutdown)
999 drv->shutdown(dev);
1000 else
1001 dev_dbg(&dev->core, "%s:%d: %s no shutdown method\n", __func__,
1002 __LINE__, dev->core.bus_id);
1003}
1004
1005/** 1168/**
1006 * ps3_vuart_bus - The vuart bus instance. 1169 * ps3_vuart_shutdown - Cleans interrupts and HV resources.
1170 * @dev: The struct ps3_system_bus_device instance.
1007 * 1171 *
1008 * The vuart is managed as a bus that port devices connect to. 1172 * Cleans interrupts and HV resources. After this call the
1173 * device can still be used in polling mode. This behavior required
1174 * by sys-manager to be able to complete the device power operation
1175 * sequence.
1009 */ 1176 */
1010 1177
1011struct bus_type ps3_vuart_bus = { 1178static int ps3_vuart_shutdown(struct ps3_system_bus_device *dev)
1012 .name = "ps3_vuart",
1013 .match = ps3_vuart_match,
1014 .probe = ps3_vuart_probe,
1015 .remove = ps3_vuart_remove,
1016 .shutdown = ps3_vuart_shutdown,
1017};
1018
1019int __init ps3_vuart_bus_init(void)
1020{ 1179{
1021 int result; 1180 struct ps3_vuart_port_driver *drv;
1022 1181
1023 pr_debug("%s:%d:\n", __func__, __LINE__); 1182 BUG_ON(!dev);
1024 1183
1025 if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) 1184 down(&vuart_bus_priv.probe_mutex);
1026 return -ENODEV;
1027 1185
1028 init_MUTEX(&vuart_bus_priv.probe_mutex); 1186 dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
1029 result = bus_register(&ps3_vuart_bus); 1187 dev->match_id);
1030 BUG_ON(result);
1031 1188
1032 return result; 1189 if (!dev->core.driver) {
1033} 1190 dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
1191 __LINE__);
1192 up(&vuart_bus_priv.probe_mutex);
1193 return 0;
1194 }
1034 1195
1035void __exit ps3_vuart_bus_exit(void) 1196 drv = ps3_system_bus_dev_to_vuart_drv(dev);
1036{
1037 pr_debug("%s:%d:\n", __func__, __LINE__);
1038 bus_unregister(&ps3_vuart_bus);
1039}
1040 1197
1041core_initcall(ps3_vuart_bus_init); 1198 BUG_ON(!drv);
1042module_exit(ps3_vuart_bus_exit);
1043 1199
1044/** 1200 if (drv->shutdown)
1045 * ps3_vuart_port_release_device - Remove a vuart port device. 1201 drv->shutdown(dev);
1046 */ 1202 else if (drv->remove) {
1203 dev_dbg(&dev->core, "%s:%d: no shutdown, calling remove\n",
1204 __func__, __LINE__);
1205 drv->remove(dev);
1206 } else {
1207 dev_dbg(&dev->core, "%s:%d: no shutdown method\n", __func__,
1208 __LINE__);
1209 BUG();
1210 }
1047 1211
1048static void ps3_vuart_port_release_device(struct device *_dev) 1212 ps3_vuart_cleanup(dev);
1049{
1050#if defined(DEBUG)
1051 struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
1052 1213
1053 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); 1214 dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
1054 1215
1055 BUG_ON(dev->priv && "forgot to free"); 1216 up(&vuart_bus_priv.probe_mutex);
1056 memset(&dev->core, 0, sizeof(dev->core)); 1217 return 0;
1057#endif
1058} 1218}
1059 1219
1060/** 1220static int __init ps3_vuart_bus_init(void)
1061 * ps3_vuart_port_device_register - Add a vuart port device.
1062 */
1063
1064int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev)
1065{ 1221{
1066 static unsigned int dev_count = 1; 1222 pr_debug("%s:%d:\n", __func__, __LINE__);
1067
1068 BUG_ON(dev->priv && "forgot to free");
1069 1223
1070 dev->core.parent = NULL; 1224 if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
1071 dev->core.bus = &ps3_vuart_bus; 1225 return -ENODEV;
1072 dev->core.release = ps3_vuart_port_release_device;
1073 1226
1074 snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x", 1227 init_MUTEX(&vuart_bus_priv.probe_mutex);
1075 dev_count++);
1076 1228
1077 dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__); 1229 return 0;
1230}
1078 1231
1079 return device_register(&dev->core); 1232static void __exit ps3_vuart_bus_exit(void)
1233{
1234 pr_debug("%s:%d:\n", __func__, __LINE__);
1080} 1235}
1081 1236
1082EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register); 1237core_initcall(ps3_vuart_bus_init);
1238module_exit(ps3_vuart_bus_exit);
1083 1239
1084/** 1240/**
1085 * ps3_vuart_port_driver_register - Add a vuart port device driver. 1241 * ps3_vuart_port_driver_register - Add a vuart port device driver.
@@ -1089,12 +1245,18 @@ int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv)
1089{ 1245{
1090 int result; 1246 int result;
1091 1247
1092 pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name); 1248 pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name);
1093 drv->core.bus = &ps3_vuart_bus; 1249
1094 result = driver_register(&drv->core); 1250 BUG_ON(!drv->core.match_id);
1251 BUG_ON(!drv->core.core.name);
1252
1253 drv->core.probe = ps3_vuart_probe;
1254 drv->core.remove = ps3_vuart_remove;
1255 drv->core.shutdown = ps3_vuart_shutdown;
1256
1257 result = ps3_system_bus_driver_register(&drv->core);
1095 return result; 1258 return result;
1096} 1259}
1097
1098EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register); 1260EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register);
1099 1261
1100/** 1262/**
@@ -1103,8 +1265,7 @@ EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register);
1103 1265
1104void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv) 1266void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv)
1105{ 1267{
1106 pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name); 1268 pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name);
1107 driver_unregister(&drv->core); 1269 ps3_system_bus_driver_unregister(&drv->core);
1108} 1270}
1109
1110EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister); 1271EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister);
diff --git a/drivers/ps3/vuart.h b/drivers/ps3/vuart.h
index 1be992d568c8..eb7f6d94a890 100644
--- a/drivers/ps3/vuart.h
+++ b/drivers/ps3/vuart.h
@@ -34,29 +34,7 @@ struct ps3_vuart_stats {
34struct ps3_vuart_work { 34struct ps3_vuart_work {
35 struct work_struct work; 35 struct work_struct work;
36 unsigned long trigger; 36 unsigned long trigger;
37 spinlock_t lock; 37 struct ps3_system_bus_device *dev; /* to convert work to device */
38 struct ps3_vuart_port_device* dev; /* to convert work to device */
39};
40
41/**
42 * struct ps3_vuart_port_priv - private vuart device data.
43 */
44
45struct ps3_vuart_port_priv {
46 unsigned int port_number;
47 u64 interrupt_mask;
48
49 struct {
50 spinlock_t lock;
51 struct list_head head;
52 } tx_list;
53 struct {
54 unsigned long bytes_held;
55 spinlock_t lock;
56 struct list_head head;
57 } rx_list;
58 struct ps3_vuart_stats stats;
59 struct ps3_vuart_work work;
60}; 38};
61 39
62/** 40/**
@@ -64,32 +42,30 @@ struct ps3_vuart_port_priv {
64 */ 42 */
65 43
66struct ps3_vuart_port_driver { 44struct ps3_vuart_port_driver {
67 enum ps3_match_id match_id; 45 struct ps3_system_bus_driver core;
68 struct device_driver core; 46 int (*probe)(struct ps3_system_bus_device *);
69 int (*probe)(struct ps3_vuart_port_device *); 47 int (*remove)(struct ps3_system_bus_device *);
70 int (*remove)(struct ps3_vuart_port_device *); 48 void (*shutdown)(struct ps3_system_bus_device *);
71 void (*shutdown)(struct ps3_vuart_port_device *); 49 void (*work)(struct ps3_system_bus_device *);
72 int (*tx_event)(struct ps3_vuart_port_device *dev); 50 /* int (*tx_event)(struct ps3_system_bus_device *dev); */
73 int (*rx_event)(struct ps3_vuart_port_device *dev); 51 /* int (*rx_event)(struct ps3_system_bus_device *dev); */
74 int (*disconnect_event)(struct ps3_vuart_port_device *dev); 52 /* int (*disconnect_event)(struct ps3_system_bus_device *dev); */
75 /* int (*suspend)(struct ps3_vuart_port_device *, pm_message_t); */ 53 /* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */
76 /* int (*resume)(struct ps3_vuart_port_device *); */ 54 /* int (*resume)(struct ps3_system_bus_device *); */
77}; 55};
78 56
79int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv); 57int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv);
80void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv); 58void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv);
81 59
82static inline struct ps3_vuart_port_driver *to_ps3_vuart_port_driver( 60static inline struct ps3_vuart_port_driver *
83 struct device_driver *_drv) 61 ps3_system_bus_dev_to_vuart_drv(struct ps3_system_bus_device *_dev)
84{
85 return container_of(_drv, struct ps3_vuart_port_driver, core);
86}
87static inline struct ps3_vuart_port_device *to_ps3_vuart_port_device(
88 struct device *_dev)
89{ 62{
90 return container_of(_dev, struct ps3_vuart_port_device, core); 63 struct ps3_system_bus_driver *sbd =
64 ps3_system_bus_dev_to_system_bus_drv(_dev);
65 BUG_ON(!sbd);
66 return container_of(sbd, struct ps3_vuart_port_driver, core);
91} 67}
92static inline struct ps3_vuart_port_device *ps3_vuart_work_to_port_device( 68static inline struct ps3_system_bus_device *ps3_vuart_work_to_system_bus_dev(
93 struct work_struct *_work) 69 struct work_struct *_work)
94{ 70{
95 struct ps3_vuart_work *vw = container_of(_work, struct ps3_vuart_work, 71 struct ps3_vuart_work *vw = container_of(_work, struct ps3_vuart_work,
@@ -97,14 +73,13 @@ static inline struct ps3_vuart_port_device *ps3_vuart_work_to_port_device(
97 return vw->dev; 73 return vw->dev;
98} 74}
99 75
100int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf, 76int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf,
101 unsigned int bytes);
102int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
103 unsigned int bytes); 77 unsigned int bytes);
104int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func, 78int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf,
105 unsigned int bytes); 79 unsigned int bytes);
106void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev); 80int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes);
107void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev, 81void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev);
82void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev,
108 unsigned int bytes); 83 unsigned int bytes);
109 84
110#endif 85#endif