Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * PS3 Logical Performance Monitor.
0004  *
0005  *  Copyright (C) 2007 Sony Computer Entertainment Inc.
0006  *  Copyright 2007 Sony Corp.
0007  */
0008 
0009 #include <linux/slab.h>
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/uaccess.h>
0014 #include <asm/smp.h>
0015 #include <asm/time.h>
0016 #include <asm/ps3.h>
0017 #include <asm/lv1call.h>
0018 #include <asm/cell-pmu.h>
0019 
0020 
0021 /* BOOKMARK tag macros */
0022 #define PS3_PM_BOOKMARK_START                    0x8000000000000000ULL
0023 #define PS3_PM_BOOKMARK_STOP                     0x4000000000000000ULL
0024 #define PS3_PM_BOOKMARK_TAG_KERNEL               0x1000000000000000ULL
0025 #define PS3_PM_BOOKMARK_TAG_USER                 0x3000000000000000ULL
0026 #define PS3_PM_BOOKMARK_TAG_MASK_HI              0xF000000000000000ULL
0027 #define PS3_PM_BOOKMARK_TAG_MASK_LO              0x0F00000000000000ULL
0028 
0029 /* CBE PM CONTROL register macros */
0030 #define PS3_PM_CONTROL_PPU_TH0_BOOKMARK          0x00001000
0031 #define PS3_PM_CONTROL_PPU_TH1_BOOKMARK          0x00000800
0032 #define PS3_PM_CONTROL_PPU_COUNT_MODE_MASK       0x000C0000
0033 #define PS3_PM_CONTROL_PPU_COUNT_MODE_PROBLEM    0x00080000
0034 #define PS3_WRITE_PM_MASK                        0xFFFFFFFFFFFFFFFFULL
0035 
0036 /* CBE PM START STOP register macros */
0037 #define PS3_PM_START_STOP_PPU_TH0_BOOKMARK_START 0x02000000
0038 #define PS3_PM_START_STOP_PPU_TH1_BOOKMARK_START 0x01000000
0039 #define PS3_PM_START_STOP_PPU_TH0_BOOKMARK_STOP  0x00020000
0040 #define PS3_PM_START_STOP_PPU_TH1_BOOKMARK_STOP  0x00010000
0041 #define PS3_PM_START_STOP_START_MASK             0xFF000000
0042 #define PS3_PM_START_STOP_STOP_MASK              0x00FF0000
0043 
0044 /* CBE PM COUNTER register macres */
0045 #define PS3_PM_COUNTER_MASK_HI                   0xFFFFFFFF00000000ULL
0046 #define PS3_PM_COUNTER_MASK_LO                   0x00000000FFFFFFFFULL
0047 
0048 /* BASE SIGNAL GROUP NUMBER macros */
0049 #define PM_ISLAND2_BASE_SIGNAL_GROUP_NUMBER  0
0050 #define PM_ISLAND2_SIGNAL_GROUP_NUMBER1      6
0051 #define PM_ISLAND2_SIGNAL_GROUP_NUMBER2      7
0052 #define PM_ISLAND3_BASE_SIGNAL_GROUP_NUMBER  7
0053 #define PM_ISLAND4_BASE_SIGNAL_GROUP_NUMBER  15
0054 #define PM_SPU_TRIGGER_SIGNAL_GROUP_NUMBER   17
0055 #define PM_SPU_EVENT_SIGNAL_GROUP_NUMBER     18
0056 #define PM_ISLAND5_BASE_SIGNAL_GROUP_NUMBER  18
0057 #define PM_ISLAND6_BASE_SIGNAL_GROUP_NUMBER  24
0058 #define PM_ISLAND7_BASE_SIGNAL_GROUP_NUMBER  49
0059 #define PM_ISLAND8_BASE_SIGNAL_GROUP_NUMBER  52
0060 #define PM_SIG_GROUP_SPU                     41
0061 #define PM_SIG_GROUP_SPU_TRIGGER             42
0062 #define PM_SIG_GROUP_SPU_EVENT               43
0063 #define PM_SIG_GROUP_MFC_MAX                 60
0064 
0065 /**
0066  * struct ps3_lpm_shadow_regs - Performance monitor shadow registers.
0067  *
0068  * @pm_control: Shadow of the processor's pm_control register.
0069  * @pm_start_stop: Shadow of the processor's pm_start_stop register.
0070  * @group_control: Shadow of the processor's group_control register.
0071  * @debug_bus_control: Shadow of the processor's debug_bus_control register.
0072  *
0073  * The logical performance monitor provides a write-only interface to
0074  * these processor registers.  These shadow variables cache the processor
0075  * register values for reading.
0076  *
0077  * The initial value of the shadow registers at lpm creation is
0078  * PS3_LPM_SHADOW_REG_INIT.
0079  */
0080 
0081 struct ps3_lpm_shadow_regs {
0082     u64 pm_control;
0083     u64 pm_start_stop;
0084     u64 group_control;
0085     u64 debug_bus_control;
0086 };
0087 
0088 #define PS3_LPM_SHADOW_REG_INIT 0xFFFFFFFF00000000ULL
0089 
0090 /**
0091  * struct ps3_lpm_priv - Private lpm device data.
0092  *
0093  * @open: An atomic variable indicating the lpm driver has been opened.
0094  * @rights: The lpm rigths granted by the system policy module.  A logical
0095  *  OR of enum ps3_lpm_rights.
0096  * @node_id: The node id of a BE processor whose performance monitor this
0097  *  lpar has the right to use.
0098  * @pu_id: The lv1 id of the logical PU.
0099  * @lpm_id: The lv1 id of this lpm instance.
0100  * @outlet_id: The outlet created by lv1 for this lpm instance.
0101  * @tb_count: The number of bytes of data held in the lv1 trace buffer.
0102  * @tb_cache: Kernel buffer to receive the data from the lv1 trace buffer.
0103  *  Must be 128 byte aligned.
0104  * @tb_cache_size: Size of the kernel @tb_cache buffer.  Must be 128 byte
0105  *  aligned.
0106  * @tb_cache_internal: An unaligned buffer allocated by this driver to be
0107  *  used for the trace buffer cache when ps3_lpm_open() is called with a
0108  *  NULL tb_cache argument.  Otherwise unused.
0109  * @shadow: Processor register shadow of type struct ps3_lpm_shadow_regs.
0110  * @sbd: The struct ps3_system_bus_device attached to this driver.
0111  *
0112  * The trace buffer is a buffer allocated and used internally to the lv1
0113  * hypervisor to collect trace data.  The trace buffer cache is a guest
0114  * buffer that accepts the trace data from the trace buffer.
0115  */
0116 
0117 struct ps3_lpm_priv {
0118     atomic_t open;
0119     u64 rights;
0120     u64 node_id;
0121     u64 pu_id;
0122     u64 lpm_id;
0123     u64 outlet_id;
0124     u64 tb_count;
0125     void *tb_cache;
0126     u64 tb_cache_size;
0127     void *tb_cache_internal;
0128     struct ps3_lpm_shadow_regs shadow;
0129     struct ps3_system_bus_device *sbd;
0130 };
0131 
0132 enum {
0133     PS3_LPM_DEFAULT_TB_CACHE_SIZE = 0x4000,
0134 };
0135 
0136 /**
0137  * lpm_priv - Static instance of the lpm data.
0138  *
0139  * Since the exported routines don't support the notion of a device
0140  * instance we need to hold the instance in this static variable
0141  * and then only allow at most one instance at a time to be created.
0142  */
0143 
0144 static struct ps3_lpm_priv *lpm_priv;
0145 
0146 static struct device *sbd_core(void)
0147 {
0148     BUG_ON(!lpm_priv || !lpm_priv->sbd);
0149     return &lpm_priv->sbd->core;
0150 }
0151 
0152 /**
0153  * use_start_stop_bookmark - Enable the PPU bookmark trace.
0154  *
0155  * And it enables PPU bookmark triggers ONLY if the other triggers are not set.
0156  * The start/stop bookmarks are inserted at ps3_enable_pm() and ps3_disable_pm()
0157  * to start/stop LPM.
0158  *
0159  * Used to get good quality of the performance counter.
0160  */
0161 
0162 enum {use_start_stop_bookmark = 1,};
0163 
0164 void ps3_set_bookmark(u64 bookmark)
0165 {
0166     /*
0167      * As per the PPE book IV, to avoid bookmark loss there must
0168      * not be a traced branch within 10 cycles of setting the
0169      * SPRN_BKMK register.  The actual text is unclear if 'within'
0170      * includes cycles before the call.
0171      */
0172 
0173     asm volatile("nop;nop;nop;nop;nop;nop;nop;nop;nop;");
0174     mtspr(SPRN_BKMK, bookmark);
0175     asm volatile("nop;nop;nop;nop;nop;nop;nop;nop;nop;");
0176 }
0177 EXPORT_SYMBOL_GPL(ps3_set_bookmark);
0178 
0179 void ps3_set_pm_bookmark(u64 tag, u64 incident, u64 th_id)
0180 {
0181     u64 bookmark;
0182 
0183     bookmark = (get_tb() & 0x00000000FFFFFFFFULL) |
0184         PS3_PM_BOOKMARK_TAG_KERNEL;
0185     bookmark = ((tag << 56) & PS3_PM_BOOKMARK_TAG_MASK_LO) |
0186         (incident << 48) | (th_id << 32) | bookmark;
0187     ps3_set_bookmark(bookmark);
0188 }
0189 EXPORT_SYMBOL_GPL(ps3_set_pm_bookmark);
0190 
0191 /**
0192  * ps3_read_phys_ctr - Read physical counter registers.
0193  *
0194  * Each physical counter can act as one 32 bit counter or as two 16 bit
0195  * counters.
0196  */
0197 
0198 u32 ps3_read_phys_ctr(u32 cpu, u32 phys_ctr)
0199 {
0200     int result;
0201     u64 counter0415;
0202     u64 counter2637;
0203 
0204     if (phys_ctr >= NR_PHYS_CTRS) {
0205         dev_dbg(sbd_core(), "%s:%u: phys_ctr too big: %u\n", __func__,
0206             __LINE__, phys_ctr);
0207         return 0;
0208     }
0209 
0210     result = lv1_set_lpm_counter(lpm_priv->lpm_id, 0, 0, 0, 0, &counter0415,
0211                      &counter2637);
0212     if (result) {
0213         dev_err(sbd_core(), "%s:%u: lv1_set_lpm_counter failed: "
0214             "phys_ctr %u, %s\n", __func__, __LINE__, phys_ctr,
0215             ps3_result(result));
0216         return 0;
0217     }
0218 
0219     switch (phys_ctr) {
0220     case 0:
0221         return counter0415 >> 32;
0222     case 1:
0223         return counter0415 & PS3_PM_COUNTER_MASK_LO;
0224     case 2:
0225         return counter2637 >> 32;
0226     case 3:
0227         return counter2637 & PS3_PM_COUNTER_MASK_LO;
0228     default:
0229         BUG();
0230     }
0231     return 0;
0232 }
0233 EXPORT_SYMBOL_GPL(ps3_read_phys_ctr);
0234 
0235 /**
0236  * ps3_write_phys_ctr - Write physical counter registers.
0237  *
0238  * Each physical counter can act as one 32 bit counter or as two 16 bit
0239  * counters.
0240  */
0241 
0242 void ps3_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val)
0243 {
0244     u64 counter0415;
0245     u64 counter0415_mask;
0246     u64 counter2637;
0247     u64 counter2637_mask;
0248     int result;
0249 
0250     if (phys_ctr >= NR_PHYS_CTRS) {
0251         dev_dbg(sbd_core(), "%s:%u: phys_ctr too big: %u\n", __func__,
0252             __LINE__, phys_ctr);
0253         return;
0254     }
0255 
0256     switch (phys_ctr) {
0257     case 0:
0258         counter0415 = (u64)val << 32;
0259         counter0415_mask = PS3_PM_COUNTER_MASK_HI;
0260         counter2637 = 0x0;
0261         counter2637_mask = 0x0;
0262         break;
0263     case 1:
0264         counter0415 = (u64)val;
0265         counter0415_mask = PS3_PM_COUNTER_MASK_LO;
0266         counter2637 = 0x0;
0267         counter2637_mask = 0x0;
0268         break;
0269     case 2:
0270         counter0415 = 0x0;
0271         counter0415_mask = 0x0;
0272         counter2637 = (u64)val << 32;
0273         counter2637_mask = PS3_PM_COUNTER_MASK_HI;
0274         break;
0275     case 3:
0276         counter0415 = 0x0;
0277         counter0415_mask = 0x0;
0278         counter2637 = (u64)val;
0279         counter2637_mask = PS3_PM_COUNTER_MASK_LO;
0280         break;
0281     default:
0282         BUG();
0283     }
0284 
0285     result = lv1_set_lpm_counter(lpm_priv->lpm_id,
0286                      counter0415, counter0415_mask,
0287                      counter2637, counter2637_mask,
0288                      &counter0415, &counter2637);
0289     if (result)
0290         dev_err(sbd_core(), "%s:%u: lv1_set_lpm_counter failed: "
0291             "phys_ctr %u, val %u, %s\n", __func__, __LINE__,
0292             phys_ctr, val, ps3_result(result));
0293 }
0294 EXPORT_SYMBOL_GPL(ps3_write_phys_ctr);
0295 
0296 /**
0297  * ps3_read_ctr - Read counter.
0298  *
0299  * Read 16 or 32 bits depending on the current size of the counter.
0300  * Counters 4, 5, 6 & 7 are always 16 bit.
0301  */
0302 
0303 u32 ps3_read_ctr(u32 cpu, u32 ctr)
0304 {
0305     u32 val;
0306     u32 phys_ctr = ctr & (NR_PHYS_CTRS - 1);
0307 
0308     val = ps3_read_phys_ctr(cpu, phys_ctr);
0309 
0310     if (ps3_get_ctr_size(cpu, phys_ctr) == 16)
0311         val = (ctr < NR_PHYS_CTRS) ? (val >> 16) : (val & 0xffff);
0312 
0313     return val;
0314 }
0315 EXPORT_SYMBOL_GPL(ps3_read_ctr);
0316 
0317 /**
0318  * ps3_write_ctr - Write counter.
0319  *
0320  * Write 16 or 32 bits depending on the current size of the counter.
0321  * Counters 4, 5, 6 & 7 are always 16 bit.
0322  */
0323 
0324 void ps3_write_ctr(u32 cpu, u32 ctr, u32 val)
0325 {
0326     u32 phys_ctr;
0327     u32 phys_val;
0328 
0329     phys_ctr = ctr & (NR_PHYS_CTRS - 1);
0330 
0331     if (ps3_get_ctr_size(cpu, phys_ctr) == 16) {
0332         phys_val = ps3_read_phys_ctr(cpu, phys_ctr);
0333 
0334         if (ctr < NR_PHYS_CTRS)
0335             val = (val << 16) | (phys_val & 0xffff);
0336         else
0337             val = (val & 0xffff) | (phys_val & 0xffff0000);
0338     }
0339 
0340     ps3_write_phys_ctr(cpu, phys_ctr, val);
0341 }
0342 EXPORT_SYMBOL_GPL(ps3_write_ctr);
0343 
0344 /**
0345  * ps3_read_pm07_control - Read counter control registers.
0346  *
0347  * Each logical counter has a corresponding control register.
0348  */
0349 
0350 u32 ps3_read_pm07_control(u32 cpu, u32 ctr)
0351 {
0352     return 0;
0353 }
0354 EXPORT_SYMBOL_GPL(ps3_read_pm07_control);
0355 
0356 /**
0357  * ps3_write_pm07_control - Write counter control registers.
0358  *
0359  * Each logical counter has a corresponding control register.
0360  */
0361 
0362 void ps3_write_pm07_control(u32 cpu, u32 ctr, u32 val)
0363 {
0364     int result;
0365     static const u64 mask = 0xFFFFFFFFFFFFFFFFULL;
0366     u64 old_value;
0367 
0368     if (ctr >= NR_CTRS) {
0369         dev_dbg(sbd_core(), "%s:%u: ctr too big: %u\n", __func__,
0370             __LINE__, ctr);
0371         return;
0372     }
0373 
0374     result = lv1_set_lpm_counter_control(lpm_priv->lpm_id, ctr, val, mask,
0375                          &old_value);
0376     if (result)
0377         dev_err(sbd_core(), "%s:%u: lv1_set_lpm_counter_control "
0378             "failed: ctr %u, %s\n", __func__, __LINE__, ctr,
0379             ps3_result(result));
0380 }
0381 EXPORT_SYMBOL_GPL(ps3_write_pm07_control);
0382 
0383 /**
0384  * ps3_read_pm - Read Other LPM control registers.
0385  */
0386 
0387 u32 ps3_read_pm(u32 cpu, enum pm_reg_name reg)
0388 {
0389     int result = 0;
0390     u64 val = 0;
0391 
0392     switch (reg) {
0393     case pm_control:
0394         return lpm_priv->shadow.pm_control;
0395     case trace_address:
0396         return CBE_PM_TRACE_BUF_EMPTY;
0397     case pm_start_stop:
0398         return lpm_priv->shadow.pm_start_stop;
0399     case pm_interval:
0400         result = lv1_set_lpm_interval(lpm_priv->lpm_id, 0, 0, &val);
0401         if (result) {
0402             val = 0;
0403             dev_dbg(sbd_core(), "%s:%u: lv1 set_interval failed: "
0404                 "reg %u, %s\n", __func__, __LINE__, reg,
0405                 ps3_result(result));
0406         }
0407         return (u32)val;
0408     case group_control:
0409         return lpm_priv->shadow.group_control;
0410     case debug_bus_control:
0411         return lpm_priv->shadow.debug_bus_control;
0412     case pm_status:
0413         result = lv1_get_lpm_interrupt_status(lpm_priv->lpm_id,
0414                               &val);
0415         if (result) {
0416             val = 0;
0417             dev_dbg(sbd_core(), "%s:%u: lv1 get_lpm_status failed: "
0418                 "reg %u, %s\n", __func__, __LINE__, reg,
0419                 ps3_result(result));
0420         }
0421         return (u32)val;
0422     case ext_tr_timer:
0423         return 0;
0424     default:
0425         dev_dbg(sbd_core(), "%s:%u: unknown reg: %d\n", __func__,
0426             __LINE__, reg);
0427         BUG();
0428         break;
0429     }
0430 
0431     return 0;
0432 }
0433 EXPORT_SYMBOL_GPL(ps3_read_pm);
0434 
0435 /**
0436  * ps3_write_pm - Write Other LPM control registers.
0437  */
0438 
0439 void ps3_write_pm(u32 cpu, enum pm_reg_name reg, u32 val)
0440 {
0441     int result = 0;
0442     u64 dummy;
0443 
0444     switch (reg) {
0445     case group_control:
0446         if (val != lpm_priv->shadow.group_control)
0447             result = lv1_set_lpm_group_control(lpm_priv->lpm_id,
0448                                val,
0449                                PS3_WRITE_PM_MASK,
0450                                &dummy);
0451         lpm_priv->shadow.group_control = val;
0452         break;
0453     case debug_bus_control:
0454         if (val != lpm_priv->shadow.debug_bus_control)
0455             result = lv1_set_lpm_debug_bus_control(lpm_priv->lpm_id,
0456                                   val,
0457                                   PS3_WRITE_PM_MASK,
0458                                   &dummy);
0459         lpm_priv->shadow.debug_bus_control = val;
0460         break;
0461     case pm_control:
0462         if (use_start_stop_bookmark)
0463             val |= (PS3_PM_CONTROL_PPU_TH0_BOOKMARK |
0464                 PS3_PM_CONTROL_PPU_TH1_BOOKMARK);
0465         if (val != lpm_priv->shadow.pm_control)
0466             result = lv1_set_lpm_general_control(lpm_priv->lpm_id,
0467                                  val,
0468                                  PS3_WRITE_PM_MASK,
0469                                  0, 0, &dummy,
0470                                  &dummy);
0471         lpm_priv->shadow.pm_control = val;
0472         break;
0473     case pm_interval:
0474         result = lv1_set_lpm_interval(lpm_priv->lpm_id, val,
0475                           PS3_WRITE_PM_MASK, &dummy);
0476         break;
0477     case pm_start_stop:
0478         if (val != lpm_priv->shadow.pm_start_stop)
0479             result = lv1_set_lpm_trigger_control(lpm_priv->lpm_id,
0480                                  val,
0481                                  PS3_WRITE_PM_MASK,
0482                                  &dummy);
0483         lpm_priv->shadow.pm_start_stop = val;
0484         break;
0485     case trace_address:
0486     case ext_tr_timer:
0487     case pm_status:
0488         break;
0489     default:
0490         dev_dbg(sbd_core(), "%s:%u: unknown reg: %d\n", __func__,
0491             __LINE__, reg);
0492         BUG();
0493         break;
0494     }
0495 
0496     if (result)
0497         dev_err(sbd_core(), "%s:%u: lv1 set_control failed: "
0498             "reg %u, %s\n", __func__, __LINE__, reg,
0499             ps3_result(result));
0500 }
0501 EXPORT_SYMBOL_GPL(ps3_write_pm);
0502 
0503 /**
0504  * ps3_get_ctr_size - Get the size of a physical counter.
0505  *
0506  * Returns either 16 or 32.
0507  */
0508 
0509 u32 ps3_get_ctr_size(u32 cpu, u32 phys_ctr)
0510 {
0511     u32 pm_ctrl;
0512 
0513     if (phys_ctr >= NR_PHYS_CTRS) {
0514         dev_dbg(sbd_core(), "%s:%u: phys_ctr too big: %u\n", __func__,
0515             __LINE__, phys_ctr);
0516         return 0;
0517     }
0518 
0519     pm_ctrl = ps3_read_pm(cpu, pm_control);
0520     return (pm_ctrl & CBE_PM_16BIT_CTR(phys_ctr)) ? 16 : 32;
0521 }
0522 EXPORT_SYMBOL_GPL(ps3_get_ctr_size);
0523 
0524 /**
0525  * ps3_set_ctr_size - Set the size of a physical counter to 16 or 32 bits.
0526  */
0527 
0528 void ps3_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size)
0529 {
0530     u32 pm_ctrl;
0531 
0532     if (phys_ctr >= NR_PHYS_CTRS) {
0533         dev_dbg(sbd_core(), "%s:%u: phys_ctr too big: %u\n", __func__,
0534             __LINE__, phys_ctr);
0535         return;
0536     }
0537 
0538     pm_ctrl = ps3_read_pm(cpu, pm_control);
0539 
0540     switch (ctr_size) {
0541     case 16:
0542         pm_ctrl |= CBE_PM_16BIT_CTR(phys_ctr);
0543         ps3_write_pm(cpu, pm_control, pm_ctrl);
0544         break;
0545 
0546     case 32:
0547         pm_ctrl &= ~CBE_PM_16BIT_CTR(phys_ctr);
0548         ps3_write_pm(cpu, pm_control, pm_ctrl);
0549         break;
0550     default:
0551         BUG();
0552     }
0553 }
0554 EXPORT_SYMBOL_GPL(ps3_set_ctr_size);
0555 
0556 static u64 pm_translate_signal_group_number_on_island2(u64 subgroup)
0557 {
0558 
0559     if (subgroup == 2)
0560         subgroup = 3;
0561 
0562     if (subgroup <= 6)
0563         return PM_ISLAND2_BASE_SIGNAL_GROUP_NUMBER + subgroup;
0564     else if (subgroup == 7)
0565         return PM_ISLAND2_SIGNAL_GROUP_NUMBER1;
0566     else
0567         return PM_ISLAND2_SIGNAL_GROUP_NUMBER2;
0568 }
0569 
0570 static u64 pm_translate_signal_group_number_on_island3(u64 subgroup)
0571 {
0572 
0573     switch (subgroup) {
0574     case 2:
0575     case 3:
0576     case 4:
0577         subgroup += 2;
0578         break;
0579     case 5:
0580         subgroup = 8;
0581         break;
0582     default:
0583         break;
0584     }
0585     return PM_ISLAND3_BASE_SIGNAL_GROUP_NUMBER + subgroup;
0586 }
0587 
0588 static u64 pm_translate_signal_group_number_on_island4(u64 subgroup)
0589 {
0590     return PM_ISLAND4_BASE_SIGNAL_GROUP_NUMBER + subgroup;
0591 }
0592 
0593 static u64 pm_translate_signal_group_number_on_island5(u64 subgroup)
0594 {
0595 
0596     switch (subgroup) {
0597     case 3:
0598         subgroup = 4;
0599         break;
0600     case 4:
0601         subgroup = 6;
0602         break;
0603     default:
0604         break;
0605     }
0606     return PM_ISLAND5_BASE_SIGNAL_GROUP_NUMBER + subgroup;
0607 }
0608 
0609 static u64 pm_translate_signal_group_number_on_island6(u64 subgroup,
0610                                u64 subsubgroup)
0611 {
0612     switch (subgroup) {
0613     case 3:
0614     case 4:
0615     case 5:
0616         subgroup += 1;
0617         break;
0618     default:
0619         break;
0620     }
0621 
0622     switch (subsubgroup) {
0623     case 4:
0624     case 5:
0625     case 6:
0626         subsubgroup += 2;
0627         break;
0628     case 7:
0629     case 8:
0630     case 9:
0631     case 10:
0632         subsubgroup += 4;
0633         break;
0634     case 11:
0635     case 12:
0636     case 13:
0637         subsubgroup += 5;
0638         break;
0639     default:
0640         break;
0641     }
0642 
0643     if (subgroup <= 5)
0644         return (PM_ISLAND6_BASE_SIGNAL_GROUP_NUMBER + subgroup);
0645     else
0646         return (PM_ISLAND6_BASE_SIGNAL_GROUP_NUMBER + subgroup
0647             + subsubgroup - 1);
0648 }
0649 
0650 static u64 pm_translate_signal_group_number_on_island7(u64 subgroup)
0651 {
0652     return PM_ISLAND7_BASE_SIGNAL_GROUP_NUMBER + subgroup;
0653 }
0654 
0655 static u64 pm_translate_signal_group_number_on_island8(u64 subgroup)
0656 {
0657     return PM_ISLAND8_BASE_SIGNAL_GROUP_NUMBER + subgroup;
0658 }
0659 
0660 static u64 pm_signal_group_to_ps3_lv1_signal_group(u64 group)
0661 {
0662     u64 island;
0663     u64 subgroup;
0664     u64 subsubgroup;
0665 
0666     subgroup = 0;
0667     subsubgroup = 0;
0668     island = 0;
0669     if (group < 1000) {
0670         if (group < 100) {
0671             if (20 <= group && group < 30) {
0672                 island = 2;
0673                 subgroup = group - 20;
0674             } else if (30 <= group && group < 40) {
0675                 island = 3;
0676                 subgroup = group - 30;
0677             } else if (40 <= group && group < 50) {
0678                 island = 4;
0679                 subgroup = group - 40;
0680             } else if (50 <= group && group < 60) {
0681                 island = 5;
0682                 subgroup = group - 50;
0683             } else if (60 <= group && group < 70) {
0684                 island = 6;
0685                 subgroup = group - 60;
0686             } else if (70 <= group && group < 80) {
0687                 island = 7;
0688                 subgroup = group - 70;
0689             } else if (80 <= group && group < 90) {
0690                 island = 8;
0691                 subgroup = group - 80;
0692             }
0693         } else if (200 <= group && group < 300) {
0694             island = 2;
0695             subgroup = group - 200;
0696         } else if (600 <= group && group < 700) {
0697             island = 6;
0698             subgroup = 5;
0699             subsubgroup = group - 650;
0700         }
0701     } else if (6000 <= group && group < 7000) {
0702         island = 6;
0703         subgroup = 5;
0704         subsubgroup = group - 6500;
0705     }
0706 
0707     switch (island) {
0708     case 2:
0709         return pm_translate_signal_group_number_on_island2(subgroup);
0710     case 3:
0711         return pm_translate_signal_group_number_on_island3(subgroup);
0712     case 4:
0713         return pm_translate_signal_group_number_on_island4(subgroup);
0714     case 5:
0715         return pm_translate_signal_group_number_on_island5(subgroup);
0716     case 6:
0717         return pm_translate_signal_group_number_on_island6(subgroup,
0718                                    subsubgroup);
0719     case 7:
0720         return pm_translate_signal_group_number_on_island7(subgroup);
0721     case 8:
0722         return pm_translate_signal_group_number_on_island8(subgroup);
0723     default:
0724         dev_dbg(sbd_core(), "%s:%u: island not found: %llu\n", __func__,
0725             __LINE__, group);
0726         BUG();
0727         break;
0728     }
0729     return 0;
0730 }
0731 
0732 static u64 pm_bus_word_to_ps3_lv1_bus_word(u8 word)
0733 {
0734 
0735     switch (word) {
0736     case 1:
0737         return 0xF000;
0738     case 2:
0739         return 0x0F00;
0740     case 4:
0741         return 0x00F0;
0742     case 8:
0743     default:
0744         return 0x000F;
0745     }
0746 }
0747 
0748 static int __ps3_set_signal(u64 lv1_signal_group, u64 bus_select,
0749                 u64 signal_select, u64 attr1, u64 attr2, u64 attr3)
0750 {
0751     int ret;
0752 
0753     ret = lv1_set_lpm_signal(lpm_priv->lpm_id, lv1_signal_group, bus_select,
0754                  signal_select, attr1, attr2, attr3);
0755     if (ret)
0756         dev_err(sbd_core(),
0757             "%s:%u: error:%d 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx\n",
0758             __func__, __LINE__, ret, lv1_signal_group, bus_select,
0759             signal_select, attr1, attr2, attr3);
0760 
0761     return ret;
0762 }
0763 
0764 int ps3_set_signal(u64 signal_group, u8 signal_bit, u16 sub_unit,
0765            u8 bus_word)
0766 {
0767     int ret;
0768     u64 lv1_signal_group;
0769     u64 bus_select;
0770     u64 signal_select;
0771     u64 attr1, attr2, attr3;
0772 
0773     if (signal_group == 0)
0774         return __ps3_set_signal(0, 0, 0, 0, 0, 0);
0775 
0776     lv1_signal_group =
0777         pm_signal_group_to_ps3_lv1_signal_group(signal_group);
0778     bus_select = pm_bus_word_to_ps3_lv1_bus_word(bus_word);
0779 
0780     switch (signal_group) {
0781     case PM_SIG_GROUP_SPU_TRIGGER:
0782         signal_select = 1;
0783         signal_select = signal_select << (63 - signal_bit);
0784         break;
0785     case PM_SIG_GROUP_SPU_EVENT:
0786         signal_select = 1;
0787         signal_select = (signal_select << (63 - signal_bit)) | 0x3;
0788         break;
0789     default:
0790         signal_select = 0;
0791         break;
0792     }
0793 
0794     /*
0795      * 0: physical object.
0796      * 1: logical object.
0797      * This parameter is only used for the PPE and SPE signals.
0798      */
0799     attr1 = 1;
0800 
0801     /*
0802      * This parameter is used to specify the target physical/logical
0803      * PPE/SPE object.
0804      */
0805     if (PM_SIG_GROUP_SPU <= signal_group &&
0806         signal_group < PM_SIG_GROUP_MFC_MAX)
0807         attr2 = sub_unit;
0808     else
0809         attr2 = lpm_priv->pu_id;
0810 
0811     /*
0812      * This parameter is only used for setting the SPE signal.
0813      */
0814     attr3 = 0;
0815 
0816     ret = __ps3_set_signal(lv1_signal_group, bus_select, signal_select,
0817                    attr1, attr2, attr3);
0818     if (ret)
0819         dev_err(sbd_core(), "%s:%u: __ps3_set_signal failed: %d\n",
0820             __func__, __LINE__, ret);
0821 
0822     return ret;
0823 }
0824 EXPORT_SYMBOL_GPL(ps3_set_signal);
0825 
0826 u32 ps3_get_hw_thread_id(int cpu)
0827 {
0828     return get_hard_smp_processor_id(cpu);
0829 }
0830 EXPORT_SYMBOL_GPL(ps3_get_hw_thread_id);
0831 
0832 /**
0833  * ps3_enable_pm - Enable the entire performance monitoring unit.
0834  *
0835  * When we enable the LPM, all pending writes to counters get committed.
0836  */
0837 
0838 void ps3_enable_pm(u32 cpu)
0839 {
0840     int result;
0841     u64 tmp;
0842     int insert_bookmark = 0;
0843 
0844     lpm_priv->tb_count = 0;
0845 
0846     if (use_start_stop_bookmark) {
0847         if (!(lpm_priv->shadow.pm_start_stop &
0848             (PS3_PM_START_STOP_START_MASK
0849             | PS3_PM_START_STOP_STOP_MASK))) {
0850             result = lv1_set_lpm_trigger_control(lpm_priv->lpm_id,
0851                 (PS3_PM_START_STOP_PPU_TH0_BOOKMARK_START |
0852                 PS3_PM_START_STOP_PPU_TH1_BOOKMARK_START |
0853                 PS3_PM_START_STOP_PPU_TH0_BOOKMARK_STOP |
0854                 PS3_PM_START_STOP_PPU_TH1_BOOKMARK_STOP),
0855                 0xFFFFFFFFFFFFFFFFULL, &tmp);
0856 
0857             if (result)
0858                 dev_err(sbd_core(), "%s:%u: "
0859                     "lv1_set_lpm_trigger_control failed: "
0860                     "%s\n", __func__, __LINE__,
0861                     ps3_result(result));
0862 
0863             insert_bookmark = !result;
0864         }
0865     }
0866 
0867     result = lv1_start_lpm(lpm_priv->lpm_id);
0868 
0869     if (result)
0870         dev_err(sbd_core(), "%s:%u: lv1_start_lpm failed: %s\n",
0871             __func__, __LINE__, ps3_result(result));
0872 
0873     if (use_start_stop_bookmark && !result && insert_bookmark)
0874         ps3_set_bookmark(get_tb() | PS3_PM_BOOKMARK_START);
0875 }
0876 EXPORT_SYMBOL_GPL(ps3_enable_pm);
0877 
0878 /**
0879  * ps3_disable_pm - Disable the entire performance monitoring unit.
0880  */
0881 
0882 void ps3_disable_pm(u32 cpu)
0883 {
0884     int result;
0885     u64 tmp;
0886 
0887     ps3_set_bookmark(get_tb() | PS3_PM_BOOKMARK_STOP);
0888 
0889     result = lv1_stop_lpm(lpm_priv->lpm_id, &tmp);
0890 
0891     if (result) {
0892         if (result != LV1_WRONG_STATE)
0893             dev_err(sbd_core(), "%s:%u: lv1_stop_lpm failed: %s\n",
0894                 __func__, __LINE__, ps3_result(result));
0895         return;
0896     }
0897 
0898     lpm_priv->tb_count = tmp;
0899 
0900     dev_dbg(sbd_core(), "%s:%u: tb_count %llu (%llxh)\n", __func__, __LINE__,
0901         lpm_priv->tb_count, lpm_priv->tb_count);
0902 }
0903 EXPORT_SYMBOL_GPL(ps3_disable_pm);
0904 
0905 /**
0906  * ps3_lpm_copy_tb - Copy data from the trace buffer to a kernel buffer.
0907  * @offset: Offset in bytes from the start of the trace buffer.
0908  * @buf: Copy destination.
0909  * @count: Maximum count of bytes to copy.
0910  * @bytes_copied: Pointer to a variable that will receive the number of
0911  *  bytes copied to @buf.
0912  *
0913  * On error @buf will contain any successfully copied trace buffer data
0914  * and bytes_copied will be set to the number of bytes successfully copied.
0915  */
0916 
0917 int ps3_lpm_copy_tb(unsigned long offset, void *buf, unsigned long count,
0918             unsigned long *bytes_copied)
0919 {
0920     int result;
0921 
0922     *bytes_copied = 0;
0923 
0924     if (!lpm_priv->tb_cache)
0925         return -EPERM;
0926 
0927     if (offset >= lpm_priv->tb_count)
0928         return 0;
0929 
0930     count = min_t(u64, count, lpm_priv->tb_count - offset);
0931 
0932     while (*bytes_copied < count) {
0933         const unsigned long request = count - *bytes_copied;
0934         u64 tmp;
0935 
0936         result = lv1_copy_lpm_trace_buffer(lpm_priv->lpm_id, offset,
0937                            request, &tmp);
0938         if (result) {
0939             dev_dbg(sbd_core(), "%s:%u: 0x%lx bytes at 0x%lx\n",
0940                 __func__, __LINE__, request, offset);
0941 
0942             dev_err(sbd_core(), "%s:%u: lv1_copy_lpm_trace_buffer "
0943                 "failed: %s\n", __func__, __LINE__,
0944                 ps3_result(result));
0945             return result == LV1_WRONG_STATE ? -EBUSY : -EINVAL;
0946         }
0947 
0948         memcpy(buf, lpm_priv->tb_cache, tmp);
0949         buf += tmp;
0950         *bytes_copied += tmp;
0951         offset += tmp;
0952     }
0953     dev_dbg(sbd_core(), "%s:%u: copied %lxh bytes\n", __func__, __LINE__,
0954         *bytes_copied);
0955 
0956     return 0;
0957 }
0958 EXPORT_SYMBOL_GPL(ps3_lpm_copy_tb);
0959 
0960 /**
0961  * ps3_lpm_copy_tb_to_user - Copy data from the trace buffer to a user buffer.
0962  * @offset: Offset in bytes from the start of the trace buffer.
0963  * @buf: A __user copy destination.
0964  * @count: Maximum count of bytes to copy.
0965  * @bytes_copied: Pointer to a variable that will receive the number of
0966  *  bytes copied to @buf.
0967  *
0968  * On error @buf will contain any successfully copied trace buffer data
0969  * and bytes_copied will be set to the number of bytes successfully copied.
0970  */
0971 
0972 int ps3_lpm_copy_tb_to_user(unsigned long offset, void __user *buf,
0973                 unsigned long count, unsigned long *bytes_copied)
0974 {
0975     int result;
0976 
0977     *bytes_copied = 0;
0978 
0979     if (!lpm_priv->tb_cache)
0980         return -EPERM;
0981 
0982     if (offset >= lpm_priv->tb_count)
0983         return 0;
0984 
0985     count = min_t(u64, count, lpm_priv->tb_count - offset);
0986 
0987     while (*bytes_copied < count) {
0988         const unsigned long request = count - *bytes_copied;
0989         u64 tmp;
0990 
0991         result = lv1_copy_lpm_trace_buffer(lpm_priv->lpm_id, offset,
0992                            request, &tmp);
0993         if (result) {
0994             dev_dbg(sbd_core(), "%s:%u: 0x%lx bytes at 0x%lx\n",
0995                 __func__, __LINE__, request, offset);
0996             dev_err(sbd_core(), "%s:%u: lv1_copy_lpm_trace_buffer "
0997                 "failed: %s\n", __func__, __LINE__,
0998                 ps3_result(result));
0999             return result == LV1_WRONG_STATE ? -EBUSY : -EINVAL;
1000         }
1001 
1002         result = copy_to_user(buf, lpm_priv->tb_cache, tmp);
1003 
1004         if (result) {
1005             dev_dbg(sbd_core(), "%s:%u: 0x%llx bytes at 0x%p\n",
1006                 __func__, __LINE__, tmp, buf);
1007             dev_err(sbd_core(), "%s:%u: copy_to_user failed: %d\n",
1008                 __func__, __LINE__, result);
1009             return -EFAULT;
1010         }
1011 
1012         buf += tmp;
1013         *bytes_copied += tmp;
1014         offset += tmp;
1015     }
1016     dev_dbg(sbd_core(), "%s:%u: copied %lxh bytes\n", __func__, __LINE__,
1017         *bytes_copied);
1018 
1019     return 0;
1020 }
1021 EXPORT_SYMBOL_GPL(ps3_lpm_copy_tb_to_user);
1022 
1023 /**
1024  * ps3_get_and_clear_pm_interrupts -
1025  *
1026  * Clearing interrupts for the entire performance monitoring unit.
1027  * Reading pm_status clears the interrupt bits.
1028  */
1029 
1030 u32 ps3_get_and_clear_pm_interrupts(u32 cpu)
1031 {
1032     return ps3_read_pm(cpu, pm_status);
1033 }
1034 EXPORT_SYMBOL_GPL(ps3_get_and_clear_pm_interrupts);
1035 
1036 /**
1037  * ps3_enable_pm_interrupts -
1038  *
1039  * Enabling interrupts for the entire performance monitoring unit.
1040  * Enables the interrupt bits in the pm_status register.
1041  */
1042 
1043 void ps3_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask)
1044 {
1045     if (mask)
1046         ps3_write_pm(cpu, pm_status, mask);
1047 }
1048 EXPORT_SYMBOL_GPL(ps3_enable_pm_interrupts);
1049 
1050 /**
1051  * ps3_enable_pm_interrupts -
1052  *
1053  * Disabling interrupts for the entire performance monitoring unit.
1054  */
1055 
1056 void ps3_disable_pm_interrupts(u32 cpu)
1057 {
1058     ps3_get_and_clear_pm_interrupts(cpu);
1059     ps3_write_pm(cpu, pm_status, 0);
1060 }
1061 EXPORT_SYMBOL_GPL(ps3_disable_pm_interrupts);
1062 
1063 /**
1064  * ps3_lpm_open - Open the logical performance monitor device.
1065  * @tb_type: Specifies the type of trace buffer lv1 should use for this lpm
1066  *  instance, specified by one of enum ps3_lpm_tb_type.
1067  * @tb_cache: Optional user supplied buffer to use as the trace buffer cache.
1068  *  If NULL, the driver will allocate and manage an internal buffer.
1069  *  Unused when when @tb_type is PS3_LPM_TB_TYPE_NONE.
1070  * @tb_cache_size: The size in bytes of the user supplied @tb_cache buffer.
1071  *  Unused when @tb_cache is NULL or @tb_type is PS3_LPM_TB_TYPE_NONE.
1072  */
1073 
1074 int ps3_lpm_open(enum ps3_lpm_tb_type tb_type, void *tb_cache,
1075     u64 tb_cache_size)
1076 {
1077     int result;
1078     u64 tb_size;
1079 
1080     BUG_ON(!lpm_priv);
1081     BUG_ON(tb_type != PS3_LPM_TB_TYPE_NONE
1082         && tb_type != PS3_LPM_TB_TYPE_INTERNAL);
1083 
1084     if (tb_type == PS3_LPM_TB_TYPE_NONE && tb_cache)
1085         dev_dbg(sbd_core(), "%s:%u: bad in vals\n", __func__, __LINE__);
1086 
1087     if (!atomic_add_unless(&lpm_priv->open, 1, 1)) {
1088         dev_dbg(sbd_core(), "%s:%u: busy\n", __func__, __LINE__);
1089         return -EBUSY;
1090     }
1091 
1092     /* Note tb_cache needs 128 byte alignment. */
1093 
1094     if (tb_type == PS3_LPM_TB_TYPE_NONE) {
1095         lpm_priv->tb_cache_size = 0;
1096         lpm_priv->tb_cache_internal = NULL;
1097         lpm_priv->tb_cache = NULL;
1098     } else if (tb_cache) {
1099         if (tb_cache != (void *)ALIGN((unsigned long)tb_cache, 128)
1100             || tb_cache_size != ALIGN(tb_cache_size, 128)) {
1101             dev_err(sbd_core(), "%s:%u: unaligned tb_cache\n",
1102                 __func__, __LINE__);
1103             result = -EINVAL;
1104             goto fail_align;
1105         }
1106         lpm_priv->tb_cache_size = tb_cache_size;
1107         lpm_priv->tb_cache_internal = NULL;
1108         lpm_priv->tb_cache = tb_cache;
1109     } else {
1110         lpm_priv->tb_cache_size = PS3_LPM_DEFAULT_TB_CACHE_SIZE;
1111         lpm_priv->tb_cache_internal = kzalloc(
1112             lpm_priv->tb_cache_size + 127, GFP_KERNEL);
1113         if (!lpm_priv->tb_cache_internal) {
1114             result = -ENOMEM;
1115             goto fail_malloc;
1116         }
1117         lpm_priv->tb_cache = (void *)ALIGN(
1118             (unsigned long)lpm_priv->tb_cache_internal, 128);
1119     }
1120 
1121     result = lv1_construct_lpm(lpm_priv->node_id, tb_type, 0, 0,
1122                 ps3_mm_phys_to_lpar(__pa(lpm_priv->tb_cache)),
1123                 lpm_priv->tb_cache_size, &lpm_priv->lpm_id,
1124                 &lpm_priv->outlet_id, &tb_size);
1125 
1126     if (result) {
1127         dev_err(sbd_core(), "%s:%u: lv1_construct_lpm failed: %s\n",
1128             __func__, __LINE__, ps3_result(result));
1129         result = -EINVAL;
1130         goto fail_construct;
1131     }
1132 
1133     lpm_priv->shadow.pm_control = PS3_LPM_SHADOW_REG_INIT;
1134     lpm_priv->shadow.pm_start_stop = PS3_LPM_SHADOW_REG_INIT;
1135     lpm_priv->shadow.group_control = PS3_LPM_SHADOW_REG_INIT;
1136     lpm_priv->shadow.debug_bus_control = PS3_LPM_SHADOW_REG_INIT;
1137 
1138     dev_dbg(sbd_core(), "%s:%u: lpm_id 0x%llx, outlet_id 0x%llx, "
1139         "tb_size 0x%llx\n", __func__, __LINE__, lpm_priv->lpm_id,
1140         lpm_priv->outlet_id, tb_size);
1141 
1142     return 0;
1143 
1144 fail_construct:
1145     kfree(lpm_priv->tb_cache_internal);
1146     lpm_priv->tb_cache_internal = NULL;
1147 fail_malloc:
1148 fail_align:
1149     atomic_dec(&lpm_priv->open);
1150     return result;
1151 }
1152 EXPORT_SYMBOL_GPL(ps3_lpm_open);
1153 
1154 /**
1155  * ps3_lpm_close - Close the lpm device.
1156  *
1157  */
1158 
1159 int ps3_lpm_close(void)
1160 {
1161     dev_dbg(sbd_core(), "%s:%u\n", __func__, __LINE__);
1162 
1163     lv1_destruct_lpm(lpm_priv->lpm_id);
1164     lpm_priv->lpm_id = 0;
1165 
1166     kfree(lpm_priv->tb_cache_internal);
1167     lpm_priv->tb_cache_internal = NULL;
1168 
1169     atomic_dec(&lpm_priv->open);
1170     return 0;
1171 }
1172 EXPORT_SYMBOL_GPL(ps3_lpm_close);
1173 
1174 static int ps3_lpm_probe(struct ps3_system_bus_device *dev)
1175 {
1176     dev_dbg(&dev->core, " -> %s:%u\n", __func__, __LINE__);
1177 
1178     if (lpm_priv) {
1179         dev_info(&dev->core, "%s:%u: called twice\n",
1180             __func__, __LINE__);
1181         return -EBUSY;
1182     }
1183 
1184     lpm_priv = kzalloc(sizeof(*lpm_priv), GFP_KERNEL);
1185 
1186     if (!lpm_priv)
1187         return -ENOMEM;
1188 
1189     lpm_priv->sbd = dev;
1190     lpm_priv->node_id = dev->lpm.node_id;
1191     lpm_priv->pu_id = dev->lpm.pu_id;
1192     lpm_priv->rights = dev->lpm.rights;
1193 
1194     dev_info(&dev->core, " <- %s:%u:\n", __func__, __LINE__);
1195 
1196     return 0;
1197 }
1198 
1199 static void ps3_lpm_remove(struct ps3_system_bus_device *dev)
1200 {
1201     dev_dbg(&dev->core, " -> %s:%u:\n", __func__, __LINE__);
1202 
1203     ps3_lpm_close();
1204 
1205     kfree(lpm_priv);
1206     lpm_priv = NULL;
1207 
1208     dev_info(&dev->core, " <- %s:%u:\n", __func__, __LINE__);
1209 }
1210 
1211 static struct ps3_system_bus_driver ps3_lpm_driver = {
1212     .match_id = PS3_MATCH_ID_LPM,
1213     .core.name  = "ps3-lpm",
1214     .core.owner = THIS_MODULE,
1215     .probe      = ps3_lpm_probe,
1216     .remove     = ps3_lpm_remove,
1217     .shutdown   = ps3_lpm_remove,
1218 };
1219 
1220 static int __init ps3_lpm_init(void)
1221 {
1222     pr_debug("%s:%d:\n", __func__, __LINE__);
1223     return ps3_system_bus_driver_register(&ps3_lpm_driver);
1224 }
1225 
1226 static void __exit ps3_lpm_exit(void)
1227 {
1228     pr_debug("%s:%d:\n", __func__, __LINE__);
1229     ps3_system_bus_driver_unregister(&ps3_lpm_driver);
1230 }
1231 
1232 module_init(ps3_lpm_init);
1233 module_exit(ps3_lpm_exit);
1234 
1235 MODULE_LICENSE("GPL v2");
1236 MODULE_DESCRIPTION("PS3 Logical Performance Monitor Driver");
1237 MODULE_AUTHOR("Sony Corporation");
1238 MODULE_ALIAS(PS3_MODULE_ALIAS_LPM);