From: Andre Heider <hidden> Date: 2011-08-01 20:02:51
This series addresses various issues and extends support when running
in lpars like GameOS. Included are some patches from Hector Martin, which
I found useful.
The ps3disk driver now creates multiple block devices instead of just one.
On the GameOS lpar we have access to all regions, and - depending on the
customizable layout - the linux partitions are likely not on the first.
The device names look similar the bsd slices, a bit unusual, but the best
I could think of. Better suggestions?
There're 2 new drivers: ps3vflash and ps3nflash. These are just modified
copies of the ps3disk driver:
diff -u drivers/block/ps3disk.c drivers/block/ps3vflash.c
and "worse":
diff -u drivers/block/ps3vflash.c drivers/block/ps3nflash.c
I'm not sure what the desired way to handle these similarities are. Should
that be merged to avoid code duplication? If so, how?
Patches are based on 2.6.39 since master doesn't boot with smp on my
console. I wasn't able to pinpoint the cause so far (not that I tried
too hard). If anything get accepted I'll rebase :)
All patches were tested with the AsbestOS bootloader from Hector
Martin (http://git.marcansoft.com/?p=asbestos.git) on a PS3 slim.
Note: There are various patches floating around from anonymous
developers. None of those are signed-off and had various issues.
While some of those do contain simliar changes, I redid everything
in this series from scratch (except the patches from Hector).
Please let me know If there're any issues!
Thanks,
Andre
Andre Heider (12):
ps3: MEMORY_HOTPLUG is not a requirement anymore
ps3: Detect the current lpar environment
ps3flash: Fix region align checks
ps3flash: Refuse to work in lpars other than OtherOS
ps3: Only prealloc the flash bounce buffer for the OtherOS lpar
ps3: Limit the number of regions per storage device
ps3stor_lib: Add support for multiple regions
ps3disk: Provide a gendisk per accessible region
ps3stor_lib: Add support for storage access flags
ps3disk: Use region flags
ps3: Add a vflash driver for lpars other than OtherOS
ps3: Add a NOR FLASH driver for PS3s without NAND
Hector Martin (3):
[PS3] Add udbg driver using the PS3 gelic Ethernet device
[PS3] Get lv1 high memory region from devtree
[PS3] Add region 1 memory early
arch/powerpc/Kconfig.debug | 8 +
arch/powerpc/include/asm/ps3.h | 9 +
arch/powerpc/include/asm/ps3stor.h | 11 +-
arch/powerpc/include/asm/udbg.h | 1 +
arch/powerpc/kernel/udbg.c | 2 +
arch/powerpc/platforms/ps3/Kconfig | 43 +++-
arch/powerpc/platforms/ps3/Makefile | 1 +
arch/powerpc/platforms/ps3/device-init.c | 16 +
arch/powerpc/platforms/ps3/gelic_udbg.c | 272 ++++++++++++++++
arch/powerpc/platforms/ps3/mm.c | 91 ++++---
arch/powerpc/platforms/ps3/platform.h | 5 +
arch/powerpc/platforms/ps3/repository.c | 19 ++
arch/powerpc/platforms/ps3/setup.c | 27 ++-
arch/powerpc/platforms/ps3/system-bus.c | 2 +
drivers/block/Makefile | 2 +
drivers/block/ps3disk.c | 136 ++++++---
drivers/block/ps3nflash.c | 473 +++++++++++++++++++++++++++
drivers/block/ps3vflash.c | 508 ++++++++++++++++++++++++++++++
drivers/char/ps3flash.c | 56 +++--
drivers/net/ps3_gelic_net.c | 3 +
drivers/net/ps3_gelic_net.h | 6 +
drivers/ps3/ps3stor_lib.c | 30 +-
drivers/scsi/ps3rom.c | 11 +-
23 files changed, 1617 insertions(+), 115 deletions(-)
create mode 100644 arch/powerpc/platforms/ps3/gelic_udbg.c
create mode 100644 drivers/block/ps3nflash.c
create mode 100644 drivers/block/ps3vflash.c
--
1.7.5.4
From: Andre Heider <hidden> Date: 2011-08-01 20:02:53
From: Hector Martin <redacted>
This lets the bootloader preallocate the high lv1 region and pass its
location to the kernel through the devtree. Thus, it can be used to hold
the initrd. If the property doesn't exist, the kernel retains the old
behavior and attempts to allocate the region itself.
Signed-off-by: Hector Martin <redacted>
[a.heider: Various cleanups to make checkpatch.pl happy]
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/platforms/ps3/mm.c | 61 +++++++++++++++++++++++++++++++++++++-
1 files changed, 59 insertions(+), 2 deletions(-)
@@ -287,6 +288,49 @@ static void ps3_mm_region_destroy(struct mem_region *r)}}+staticintps3_mm_scan_memory(unsignedlongnode,constchar*uname,+intdepth,void*data)+{+structmem_region*r=data;+void*p;+u64prop[2];+unsignedlongl;+char*type=of_get_flat_dt_prop(node,"device_type",NULL);++if(type==NULL)+return0;+if(strcmp(type,"memory")!=0)+return0;++p=of_get_flat_dt_prop(node,"sony,lv1-highmem",&l);+if(p==NULL)+return0;++BUG_ON(l!=sizeof(prop));+memcpy(prop,p,sizeof(prop));++r->base=prop[0];+r->size=prop[1];+r->offset=r->base-map.rm.size;++return-1;+}++staticintps3_mm_get_devtree_highmem(structmem_region*r)+{+r->size=r->base=r->offset=0;+of_scan_flat_dt(ps3_mm_scan_memory,r);++if(r->base&&r->size){+DBG("%s:%d got high region from devtree: %llxh %llxh\n",+__func__,__LINE__,r->base,r->size);+return0;+}else{+DBG("%s:%d no high region in devtree...\n",__func__,__LINE__);+return-1;+}+}+/***ps3_mm_add_memory-hotaddmemory*/
@@ -303,6 +347,12 @@ static int __init ps3_mm_add_memory(void)BUG_ON(!mem_init_done);+if(!map.r1.size){+DBG("%s:%d: no region 1, not adding memory\n",+__func__,__LINE__);+return0;+}+start_addr=map.rm.size;start_pfn=start_addr>>PAGE_SHIFT;nr_pages=(map.r1.size+PAGE_SIZE-1)>>PAGE_SHIFT;
@@ -1219,7 +1269,13 @@ void __init ps3_mm_init(void)/* arrange to do this in ps3_mm_add_memory */-ps3_mm_region_create(&map.r1,map.total-map.rm.size);++if(ps3_mm_get_devtree_highmem(&map.r1)==0){+map.destroy_r1=0;+}else{+ps3_mm_region_create(&map.r1,map.total-map.rm.size);+map.destroy_r1=1;+}/* correct map.total for the real total amount of memory we use */map.total=map.rm.size+map.r1.size;
@@ -331,57 +331,6 @@ static int ps3_mm_get_devtree_highmem(struct mem_region *r)}}-/**-*ps3_mm_add_memory-hotaddmemory-*/--staticint__initps3_mm_add_memory(void)-{-intresult;-unsignedlongstart_addr;-unsignedlongstart_pfn;-unsignedlongnr_pages;--if(!firmware_has_feature(FW_FEATURE_PS3_LV1))-return-ENODEV;--BUG_ON(!mem_init_done);--if(!map.r1.size){-DBG("%s:%d: no region 1, not adding memory\n",-__func__,__LINE__);-return0;-}--start_addr=map.rm.size;-start_pfn=start_addr>>PAGE_SHIFT;-nr_pages=(map.r1.size+PAGE_SIZE-1)>>PAGE_SHIFT;--DBG("%s:%d: start_addr %lxh, start_pfn %lxh, nr_pages %lxh\n",-__func__,__LINE__,start_addr,start_pfn,nr_pages);--result=add_memory(0,start_addr,map.r1.size);--if(result){-pr_err("%s:%d: add_memory failed: (%d)\n",-__func__,__LINE__,result);-returnresult;-}--memblock_add(start_addr,map.r1.size);-memblock_analyze();--result=online_pages(start_pfn,nr_pages);--if(result)-pr_err("%s:%d: online_pages failed: (%d)\n",-__func__,__LINE__,result);--returnresult;-}--device_initcall(ps3_mm_add_memory);-/*============================================================================*//* dma routines *//*============================================================================*/
@@ -1280,6 +1229,17 @@ void __init ps3_mm_init(void)/* correct map.total for the real total amount of memory we use */map.total=map.rm.size+map.r1.size;+if(!map.r1.size){+DBG("%s:%d: no region 1, not adding memory\n",+__func__,__LINE__);+}else{+DBG("%s:%d: adding memory: start %llxh, size %llxh\n",+__func__,__LINE__,map.rm.size,map.r1.size);++memblock_add(map.rm.size,map.r1.size);+memblock_analyze();+}+DBG(" <- %s:%d\n",__func__,__LINE__);}
From: Andre Heider <hidden> Date: 2011-08-01 20:02:56
There is more than the OtherOS lpar the kernel can be launched in.
Detect it by reading the ss laid repository node, and be verbose about
it.
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/include/asm/ps3.h | 7 +++++++
arch/powerpc/platforms/ps3/platform.h | 4 ++++
arch/powerpc/platforms/ps3/repository.c | 19 +++++++++++++++++++
arch/powerpc/platforms/ps3/setup.c | 22 ++++++++++++++++++++++
4 files changed, 52 insertions(+), 0 deletions(-)
@@ -232,4 +232,8 @@ int ps3_repository_read_spu_resource_id(unsigned int res_index,intps3_repository_read_vuart_av_port(unsignedint*port);intps3_repository_read_vuart_sysmgr_port(unsignedint*port);+/* repository ss info */++intps3_repository_read_ss_laid(enumps3_ss_laid*laid);+#endif
From: Andre Heider <hidden> Date: 2011-08-01 20:02:57
The region fields used by the align checks are set in
ps3stor_setup(), so move those after that call.
Signed-off-by: Andre Heider <redacted>
---
drivers/char/ps3flash.c | 30 +++++++++++++++---------------
1 files changed, 15 insertions(+), 15 deletions(-)
@@ -360,21 +360,6 @@ static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev)interror;unsignedlongtmp;-tmp=dev->regions[dev->region_idx].start*dev->blk_size;-if(tmp%FLASH_BLOCK_SIZE){-dev_err(&dev->sbd.core,-"%s:%u region start %lu is not aligned\n",__func__,-__LINE__,tmp);-return-EINVAL;-}-tmp=dev->regions[dev->region_idx].size*dev->blk_size;-if(tmp%FLASH_BLOCK_SIZE){-dev_err(&dev->sbd.core,-"%s:%u region size %lu is not aligned\n",__func__,-__LINE__,tmp);-return-EINVAL;-}-/* use static buffer, kmalloc cannot allocate 256 KiB */if(!ps3flash_bounce_buffer.address)return-ENODEV;
@@ -405,6 +390,21 @@ static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev)if(error)gotofail_free_priv;+tmp=dev->regions[dev->region_idx].start*dev->blk_size;+if(tmp%FLASH_BLOCK_SIZE){+dev_err(&dev->sbd.core,+"%s:%u region start %lu is not aligned\n",__func__,+__LINE__,tmp);+return-EINVAL;+}+tmp=dev->regions[dev->region_idx].size*dev->blk_size;+if(tmp%FLASH_BLOCK_SIZE){+dev_err(&dev->sbd.core,+"%s:%u region size %lu is not aligned\n",__func__,+__LINE__,tmp);+return-EINVAL;+}+ps3flash_misc.parent=&dev->sbd.core;error=misc_register(&ps3flash_misc);if(error){
From: Andre Heider <hidden> Date: 2011-08-01 20:02:58
The driver implements a character and misc device, meant for the
axed OtherOS to exchange various settings with GameOS.
Since Firmware 3.21 there is no GameOS support anymore to write these
settings, so limit the driver to the OtherOS environment.
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/platforms/ps3/Kconfig | 1 +
drivers/char/ps3flash.c | 7 +++++++
2 files changed, 8 insertions(+), 0 deletions(-)
From: Andre Heider <hidden> Date: 2011-08-01 20:02:59
It's only used by the ps3flash driver, which only supports the
OtherOS lpar.
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/platforms/ps3/setup.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
@@ -233,7 +233,10 @@ static void __init ps3_setup_arch(void)#endifprealloc_ps3fb_videomemory();-prealloc_ps3flash_bounce_buffer();++/* the ps3flash driver only works for OtherOS */+if(ps3_get_ss_laid()==PS3_SS_LAID_OTHEROS)+prealloc_ps3flash_bounce_buffer();ppc_md.power_save=ps3_power_save;ps3_os_area_init();
From: Andre Heider <hidden> Date: 2011-08-01 20:03:00
There can be only 8 regions, add a sanity check
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/include/asm/ps3stor.h | 1 +
arch/powerpc/platforms/ps3/device-init.c | 8 ++++++++
2 files changed, 9 insertions(+), 0 deletions(-)
From: Andre Heider <hidden> Date: 2011-08-01 20:03:01
Users (ps3disk, ps3flash and ps3rom) retain the old behavior. That is:
they still only provide access to the first accessible region.
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/include/asm/ps3stor.h | 4 ++--
drivers/block/ps3disk.c | 15 +++++++++++++--
drivers/char/ps3flash.c | 23 +++++++++++++++++------
drivers/ps3/ps3stor_lib.c | 25 ++++++++++++-------------
drivers/scsi/ps3rom.c | 11 +++++++----
5 files changed, 51 insertions(+), 27 deletions(-)
@@ -51,7 +51,6 @@ struct ps3_storage_device {unsignedintnum_regions;unsignedlongaccessible_regions;-unsignedintregion_idx;/* first accessible region */structps3_storage_regionregions[0];/* Must be last */};
@@ -42,6 +42,7 @@ struct ps3disk_private {spinlock_tlock;/* Request queue spinlock */structrequest_queue*queue;structgendisk*gendisk;+unsignedintregion_idx;/* first accessible region */unsignedintblocking_factor;structrequest*req;u64raw_capacity;
@@ -125,7 +126,7 @@ static int ps3disk_submit_request_sg(struct ps3_storage_device *dev,intwrite=rq_data_dir(req),res;constchar*op=write?"write":"read";u64start_sector,sectors;-unsignedintregion_id=dev->regions[dev->region_idx].id;+unsignedintregion_id=dev->regions[priv->region_idx].id;#ifdef DEBUGunsignedintn=0;
@@ -408,6 +409,7 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)unsignedintdevidx;structrequest_queue*queue;structgendisk*gendisk;+unsignedintregion_idx;if(dev->blk_size<512){dev_err(&dev->sbd.core,
@@ -482,6 +484,14 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)}priv->gendisk=gendisk;++/* find first accessible region */+for(region_idx=0;region_idx<dev->num_regions;region_idx++)+if(test_bit(region_idx,&dev->accessible_regions)){+priv->region_idx=region_idx;+break;+}+gendisk->major=ps3disk_major;gendisk->first_minor=devidx*PS3DISK_MINORS;gendisk->fops=&ps3disk_fops;
@@ -492,7 +502,8 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)devidx+'a');priv->blocking_factor=dev->blk_size>>9;set_capacity(gendisk,-dev->regions[dev->region_idx].size*priv->blocking_factor);+dev->regions[priv->region_idx].size*+priv->blocking_factor);dev_info(&dev->sbd.core,"%s is a %s (%llu MiB total, %lu MiB for OtherOS)\n",
@@ -36,6 +36,7 @@structps3flash_private{structmutexmutex;/* Bounce buffer mutex */u64chunk_sectors;+unsignedintregion_idx;/* first accessible region */inttag;/* Start sector of buffer, -1 if invalid */booldirty;};
@@ -46,7 +47,8 @@ static int ps3flash_read_write_sectors(struct ps3_storage_device *dev,u64start_sector,intwrite){structps3flash_private*priv=ps3_system_bus_get_drvdata(&dev->sbd);-u64res=ps3stor_read_write_sectors(dev,dev->bounce_lpar,+u64res=ps3stor_read_write_sectors(dev,priv->region_idx,+dev->bounce_lpar,start_sector,priv->chunk_sectors,write);if(res){
@@ -136,7 +139,7 @@ static ssize_t ps3flash_read(char __user *userbuf, void *kernelbuf,"%s:%u: Reading %zu bytes at position %lld to U0x%p/K0x%p\n",__func__,__LINE__,count,*pos,userbuf,kernelbuf);-size=dev->regions[dev->region_idx].size*dev->blk_size;+size=dev->regions[priv->region_idx].size*dev->blk_size;if(*pos>=size||!count)return0;
@@ -205,7 +208,7 @@ static ssize_t ps3flash_write(const char __user *userbuf,"%s:%u: Writing %zu bytes at position %lld from U0x%p/K0x%p\n",__func__,__LINE__,count,*pos,userbuf,kernelbuf);-size=dev->regions[dev->region_idx].size*dev->blk_size;+size=dev->regions[priv->region_idx].size*dev->blk_size;if(*pos>=size||!count)return0;
@@ -359,6 +362,7 @@ static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev)structps3_storage_device*dev=to_ps3_storage_device(&_dev->core);structps3flash_private*priv;interror;+unsignedintregion_idx;unsignedlongtmp;/* use static buffer, kmalloc cannot allocate 256 KiB */
@@ -391,14 +395,21 @@ static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev)if(error)gotofail_free_priv;-tmp=dev->regions[dev->region_idx].start*dev->blk_size;+/* find first accessible region */+for(region_idx=0;region_idx<dev->num_regions;region_idx++)+if(test_bit(region_idx,&dev->accessible_regions)){+priv->region_idx=region_idx;+break;+}++tmp=dev->regions[priv->region_idx].start*dev->blk_size;if(tmp%FLASH_BLOCK_SIZE){dev_err(&dev->sbd.core,"%s:%u region start %lu is not aligned\n",__func__,__LINE__,tmp);return-EINVAL;}-tmp=dev->regions[dev->region_idx].size*dev->blk_size;+tmp=dev->regions[priv->region_idx].size*dev->blk_size;if(tmp%FLASH_BLOCK_SIZE){dev_err(&dev->sbd.core,"%s:%u region size %lu is not aligned\n",__func__,
@@ -101,9 +101,8 @@ static int ps3stor_probe_access(struct ps3_storage_device *dev)"%s:%u: checking accessibility of region %u\n",__func__,__LINE__,i);-dev->region_idx=i;-res=ps3stor_read_write_sectors(dev,dev->bounce_lpar,0,1,-0);+res=ps3stor_read_write_sectors(dev,i,dev->bounce_lpar,+0,1,0);if(res){dev_dbg(&dev->sbd.core,"%s:%u: read failed, ""region %u is not accessible\n",__func__,
@@ -117,6 +116,11 @@ static int ps3stor_probe_access(struct ps3_storage_device *dev)/* We can access at least one region */error=0;++dev_info(&dev->sbd.core,+"Accessible region found: #%u start %llu size %llu\n",+i,dev->regions[i].start,dev->regions[i].size);+}if(error)returnerror;
@@ -124,15 +128,8 @@ static int ps3stor_probe_access(struct ps3_storage_device *dev)n=hweight_long(dev->accessible_regions);if(n>1)dev_info(&dev->sbd.core,-"%s:%u: %lu accessible regions found. Only the first "-"one will be used\n",+"%s:%u: %lu accessible regions found\n",__func__,__LINE__,n);-dev->region_idx=__ffs(dev->accessible_regions);-dev_info(&dev->sbd.core,-"First accessible region has index %u start %llu size %llu\n",-dev->region_idx,dev->regions[dev->region_idx].start,-dev->regions[dev->region_idx].size);-return0;}
From: Andre Heider <hidden> Date: 2011-08-01 20:03:02
This changes the behavior to name the block devices for lpars
other than OtherOS. Instead of a single disk with an alphanumeric
suffix (/dev/ps3da), disks are now numeric, while each
accessible region gets its own alphanumeric suffix:
/dev/ps3d1a
/dev/ps3d1b
The old behavior for OtherOS is kept:
- only one region will be exposed as block device
- the block device name stays the same
Signed-off-by: Andre Heider <redacted>
---
drivers/block/ps3disk.c | 118 ++++++++++++++++++++++++++++++----------------
1 files changed, 77 insertions(+), 41 deletions(-)
@@ -35,18 +35,19 @@#define PS3DISK_MINORS 16-#define PS3DISK_NAME "ps3d%c"+#define PS3DISK_NAME_OTHEROS "ps3d%c"+#define PS3DISK_NAME "ps3d%c%c"structps3disk_private{spinlock_tlock;/* Request queue spinlock */structrequest_queue*queue;-structgendisk*gendisk;-unsignedintregion_idx;/* first accessible region */unsignedintblocking_factor;structrequest*req;+unsignedintdevidx;u64raw_capacity;unsignedcharmodel[ATA_ID_PROD_LEN+1];+structgendisk*gendisk[0];/* Must be last */};
@@ -126,7 +127,9 @@ static int ps3disk_submit_request_sg(struct ps3_storage_device *dev,intwrite=rq_data_dir(req),res;constchar*op=write?"write":"read";u64start_sector,sectors;-unsignedintregion_id=dev->regions[priv->region_idx].id;+unsignedintregion_idx=MINOR(disk_devt(req->rq_disk))&+(PS3DISK_MINORS-1);+unsignedintregion_id=dev->regions[region_idx].id;#ifdef DEBUGunsignedintn=0;
@@ -410,6 +413,7 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)structrequest_queue*queue;structgendisk*gendisk;unsignedintregion_idx;+unsignedintotheros=ps3_get_ss_laid()==PS3_SS_LAID_OTHEROS;if(dev->blk_size<512){dev_err(&dev->sbd.core,
@@ -430,7 +434,9 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)__set_bit(devidx,&ps3disk_mask);mutex_unlock(&ps3disk_mask_mutex);-priv=kzalloc(sizeof(*priv),GFP_KERNEL);+priv=kzalloc(sizeof(*priv)++dev->num_regions*sizeof(structgendisk),+GFP_KERNEL);if(!priv){error=-ENOMEM;gotofail;
@@ -450,6 +456,7 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)if(error)gotofail_free_bounce;+priv->devidx=devidx;ps3disk_identify(dev);queue=blk_init_queue(ps3disk_request,&priv->lock);
@@ -475,45 +482,60 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)blk_queue_max_segments(queue,-1);blk_queue_max_segment_size(queue,dev->bounce_size);-gendisk=alloc_disk(PS3DISK_MINORS);-if(!gendisk){-dev_err(&dev->sbd.core,"%s:%u: alloc_disk failed\n",__func__,-__LINE__);-error=-ENOMEM;-gotofail_cleanup_queue;-}+dev_info(&dev->sbd.core,"%s (%llu MiB)\n",+priv->model,priv->raw_capacity>>11);-priv->gendisk=gendisk;+for(region_idx=0;region_idx<dev->num_regions;region_idx++){+if(test_bit(region_idx,&dev->accessible_regions)==0)+continue;-/* find first accessible region */-for(region_idx=0;region_idx<dev->num_regions;region_idx++)-if(test_bit(region_idx,&dev->accessible_regions)){-priv->region_idx=region_idx;-break;+gendisk=alloc_disk(PS3DISK_MINORS*PS3_STORAGE_MAX_REGIONS);+if(!gendisk){+dev_err(&dev->sbd.core,"%s:%u: alloc_disk failed\n",+__func__,__LINE__);+error=-ENOMEM;+gotofail_cleanup_queue;}-gendisk->major=ps3disk_major;-gendisk->first_minor=devidx*PS3DISK_MINORS;-gendisk->fops=&ps3disk_fops;-gendisk->queue=queue;-gendisk->private_data=dev;-gendisk->driverfs_dev=&dev->sbd.core;-snprintf(gendisk->disk_name,sizeof(gendisk->disk_name),PS3DISK_NAME,-devidx+'a');-priv->blocking_factor=dev->blk_size>>9;-set_capacity(gendisk,-dev->regions[priv->region_idx].size*-priv->blocking_factor);--dev_info(&dev->sbd.core,-"%s is a %s (%llu MiB total, %lu MiB for OtherOS)\n",-gendisk->disk_name,priv->model,priv->raw_capacity>>11,-get_capacity(gendisk)>>11);--add_disk(gendisk);+priv->gendisk[region_idx]=gendisk;+gendisk->major=ps3disk_major;+gendisk->first_minor=devidx*PS3DISK_MINORS+region_idx;+gendisk->fops=&ps3disk_fops;+gendisk->queue=queue;+gendisk->private_data=dev;+gendisk->driverfs_dev=&dev->sbd.core;++if(otheros){+/* keep the old block device name for OtherOS */+snprintf(gendisk->disk_name,sizeof(gendisk->disk_name),+PS3DISK_NAME_OTHEROS,'a'+devidx);+}else{+snprintf(gendisk->disk_name,sizeof(gendisk->disk_name),+PS3DISK_NAME,'1'+devidx,'a'+region_idx);+}++priv->blocking_factor=dev->blk_size>>9;+set_capacity(gendisk,dev->regions[region_idx].size*+priv->blocking_factor);++dev_info(&dev->sbd.core,+"%s (%lu MiB region)\n",+gendisk->disk_name,get_capacity(gendisk)>>11);++add_disk(gendisk);++/* keep old behavior for OtherOS - only one region */+if(otheros)+break;+}+return0;fail_cleanup_queue:+for(region_idx=0;region_idx<dev->num_regions;region_idx++)+if(priv->gendisk[region_idx])+del_gendisk(priv->gendisk[region_idx]);+blk_cleanup_queue(queue);fail_teardown:ps3stor_teardown(dev);
@@ -533,14 +555,28 @@ static int ps3disk_remove(struct ps3_system_bus_device *_dev){structps3_storage_device*dev=to_ps3_storage_device(&_dev->core);structps3disk_private*priv=ps3_system_bus_get_drvdata(&dev->sbd);+unsignedintregion_idx;mutex_lock(&ps3disk_mask_mutex);-__clear_bit(MINOR(disk_devt(priv->gendisk))/PS3DISK_MINORS,-&ps3disk_mask);+__clear_bit(priv->devidx,&ps3disk_mask);mutex_unlock(&ps3disk_mask_mutex);-del_gendisk(priv->gendisk);++for(region_idx=0;region_idx<dev->num_regions;region_idx++){+if(test_bit(region_idx,&dev->accessible_regions)==0)+continue;++del_gendisk(priv->gendisk[region_idx]);+}+blk_cleanup_queue(priv->queue);-put_disk(priv->gendisk);++for(region_idx=0;region_idx<dev->num_regions;region_idx++){+if(test_bit(region_idx,&dev->accessible_regions)==0)+continue;++put_disk(priv->gendisk[region_idx]);+}+dev_notice(&dev->sbd.core,"Synchronizing disk cache\n");ps3disk_sync_cache(dev);ps3stor_teardown(dev);
From: Andre Heider <hidden> Date: 2011-08-01 20:03:03
Users can now set the access flags in the region struct. This is
required for accessing the first region, or selecting an alternative
decryption key for the vflash partitions.
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/include/asm/ps3stor.h | 8 +++++++-
arch/powerpc/platforms/ps3/device-init.c | 1 +
drivers/block/ps3disk.c | 5 +++--
drivers/ps3/ps3stor_lib.c | 5 +++--
4 files changed, 14 insertions(+), 5 deletions(-)
From: Andre Heider <hidden> Date: 2011-08-01 20:03:04
Provide a set of default region flags and make them overwritable via
a module parameter array.
Set PS3_STORAGE_FLAG_SKIP_ACL for region 0, so it can be accessed
from the GameOS lpar.
Signed-off-by: Andre Heider <redacted>
---
drivers/block/ps3disk.c | 16 ++++++++++++++++
1 files changed, 16 insertions(+), 0 deletions(-)
From: Andre Heider <hidden> Date: 2011-08-01 20:03:05
This driver refuses to work on OtherOS, and hence complements the
ps3flash driver - which only works on OtherOS.
A gendisk for each accessible region is created, and a default set
of region flags is provided - overwritable via a module param array.
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/platforms/ps3/Kconfig | 16 +-
drivers/block/Makefile | 1 +
drivers/block/ps3vflash.c | 508 ++++++++++++++++++++++++++++++++++++
3 files changed, 524 insertions(+), 1 deletions(-)
create mode 100644 drivers/block/ps3vflash.c
From: Andre Heider <hidden> Date: 2011-08-01 20:03:06
A gendisk for each accessible region is created, and a default set
of region flags is provided - overwritable via a module param array.
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/include/asm/ps3.h | 2 +
arch/powerpc/platforms/ps3/Kconfig | 15 +
arch/powerpc/platforms/ps3/device-init.c | 7 +
arch/powerpc/platforms/ps3/platform.h | 1 +
arch/powerpc/platforms/ps3/system-bus.c | 2 +
drivers/block/Makefile | 1 +
drivers/block/ps3nflash.c | 473 ++++++++++++++++++++++++++++++
7 files changed, 501 insertions(+), 0 deletions(-)
create mode 100644 drivers/block/ps3nflash.c
Gr{oetje,eeting}s,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k=
.org
In personal conversations with technical people, I call myself a hacker. Bu=
t
when I'm talking to journalists I just say "programmer" or something like t=
hat.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 -- Linus Torvalds
repo->dev_type, port, blk_size, num_blocks,
Gr{oetje,eeting}s,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k=
.org
In personal conversations with technical people, I call myself a hacker. Bu=
t
when I'm talking to journalists I just say "programmer" or something like t=
hat.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 -- Linus Torvalds
On Mon, Aug 1, 2011 at 22:03, Andre Heider [off-list ref] wrote:
Users (ps3disk, ps3flash and ps3rom) retain the old behavior. That is:
they still only provide access to the first accessible region.
Signed-off-by: Andre Heider <redacted>
---
=C2=A0arch/powerpc/include/asm/ps3stor.h | =C2=A0 =C2=A04 ++--
=C2=A0drivers/block/ps3disk.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0| =
Same in the other drivers.
Gr{oetje,eeting}s,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k=
.org
In personal conversations with technical people, I call myself a hacker. Bu=
t
when I'm talking to journalists I just say "programmer" or something like t=
hat.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 -- Linus Torvalds
From: Andre Heider <hidden> Date: 2011-08-01 20:56:31
On Mon, Aug 1, 2011 at 10:29 PM, Geert Uytterhoeven
[off-list ref] wrote:
On Mon, Aug 1, 2011 at 22:02, Andre Heider [off-list ref] wrote:
quoted
The region fields used by the align checks are set in
ps3stor_setup(), so move those after that call.
Are you sure?
Aren't they set in
arch/powerpc/platforms/ps3/device-init.c:ps3_setup_storage_dev()?
Hm right, unfortunate commit message... :)
dev->region_idx is set in ps3stor_probe_access(), which is called from
ps3stor_setup().
So the code always checked the first region, where it should check the
one beeing used.
Will fix the commit message.
Thanks
On Mon, Aug 1, 2011 at 22:56, Andre Heider [off-list ref] wrote:
On Mon, Aug 1, 2011 at 10:29 PM, Geert Uytterhoeven
[off-list ref] wrote:
quoted
On Mon, Aug 1, 2011 at 22:02, Andre Heider [off-list ref] wrote:
quoted
The region fields used by the align checks are set in
ps3stor_setup(), so move those after that call.
Are you sure?
Aren't they set in
arch/powerpc/platforms/ps3/device-init.c:ps3_setup_storage_dev()?
Hm right, unfortunate commit message... :)
dev->region_idx is set in ps3stor_probe_access(), which is called from
ps3stor_setup().
So the code always checked the first region, where it should check the
one beeing used.
IC. You're right. That's indeed a bug.
Gr{oetje,eeting}s,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k=
.org
In personal conversations with technical people, I call myself a hacker. Bu=
t
when I'm talking to journalists I just say "programmer" or something like t=
hat.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 -- Linus Torvalds
Hi Andre,
On 08/01/2011 01:02 PM, Andre Heider wrote:
This series addresses various issues and extends support when running
in lpars like GameOS. Included are some patches from Hector Martin, which
I found useful.
Much of this is just general fixups and improvements to the existing PS3
support. I think you should separate those changes out and work to get
them included, then consider others. If I give some comment, then
I consider that part worth pursuing at the present time.
I have limited time to review the patches, so it will take me a while to
get through them.
Patches are based on 2.6.39 since master doesn't boot with smp on my
console. I wasn't able to pinpoint the cause so far (not that I tried
too hard).
I'm looking into this problem, but it will take some time.
-Geoff
This lets the bootloader preallocate the high lv1 region and pass its
location to the kernel through the devtree. Thus, it can be used to hold
the initrd. If the property doesn't exist, the kernel retains the old
behavior and attempts to allocate the region itself.
With this mechanism how is the address of the initrd passed to the
new kernel, in the DT?
How would a kexec based bootloader work? If it's kernel were to allocate
high mem and the bootloader program uses the high mem, how could it tell
that kernel not to destroy the region on shutdown?
If arch/powerpc/boot/ps3.c allocated the mem and added a DT entry
then other OSes that don't know about the Linux device tree won't
be able to use that allocated memory. Other OSes could do a
test to see if the allocation was already done. Another option
that might work is to write info into the LV1 repository then
have boot code look there for allocated hig mem.
quoted hunk
Signed-off-by: Hector Martin <redacted>
[a.heider: Various cleanups to make checkpatch.pl happy]
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/platforms/ps3/mm.c | 61 +++++++++++++++++++++++++++++++++++++-
1 files changed, 59 insertions(+), 2 deletions(-)
In the general case we could have multiple high mem
regions, and each could need to be destroyed, so I
think struct mem_region should have a destroy flag.
+ return 0;
+
+ p = of_get_flat_dt_prop(node, "sony,lv1-highmem", &l);
+ if (p == NULL)
+ return 0;
+
+ BUG_ON(l != sizeof(prop));
+ memcpy(prop, p, sizeof(prop));
+
+ r->base = prop[0];
+ r->size = prop[1];
+ r->offset = r->base - map.rm.size;
+
+ return -1;
+}
+
+static int ps3_mm_get_devtree_highmem(struct mem_region *r)
+{
+ r->size = r->base = r->offset = 0;
+ of_scan_flat_dt(ps3_mm_scan_memory, r);
+
+ if (r->base && r->size) {
+ DBG("%s:%d got high region from devtree: %llxh %llxh\n",
+ __func__, __LINE__, r->base, r->size);
+ return 0;
+ } else {
+ DBG("%s:%d no high region in devtree...\n", __func__, __LINE__);
+ return -1;
+ }
+}
+
/**
* ps3_mm_add_memory - hot add memory
*/
@@ -303,6 +347,12 @@ static int __init ps3_mm_add_memory(void) BUG_ON(!mem_init_done);+ if (!map.r1.size) {+ DBG("%s:%d: no region 1, not adding memory\n",+ __func__, __LINE__);+ return 0;+ }
Did you find this to be hit? Also, in the general case,
there could be more than one high mem region, but I don't
know of any current systems that do.
@@ -1219,7 +1269,13 @@ void __init ps3_mm_init(void) /* arrange to do this in ps3_mm_add_memory */- ps3_mm_region_create(&map.r1, map.total - map.rm.size);++ if (ps3_mm_get_devtree_highmem(&map.r1) == 0) {+ map.destroy_r1 = 0;+ } else {
This should be
if (!ps3_mm_get_devtree_highmem(&map.r1))
map.destroy_r1 = 0;
else {
quoted hunk
+ ps3_mm_region_create(&map.r1, map.total - map.rm.size);
+ map.destroy_r1 = 1;
+ }
/* correct map.total for the real total amount of memory we use */
map.total = map.rm.size + map.r1.size;
@@ -39,6 +39,13 @@ union ps3_firmware_version {voidps3_get_firmware_version(unionps3_firmware_version*v);intps3_compare_firmware_version(u16major,u16minor,u16rev);+enumps3_ss_laid{+PS3_SS_LAID_GAMEOS=0x1070000002000001UL,+PS3_SS_LAID_OTHEROS=0x1080000004000001UL,
Only PS3_SS_LAID_OTHEROS is used for anything outside ps3_setup_arch(),
so I think it makes sense to split this into two patches with one adding
just PS3_SS_LAID_OTHEROS and ps3_get_ss_laid() with a comment that
it adds the ps3_get_ss_laid routine.
@@ -232,4 +232,8 @@ int ps3_repository_read_spu_resource_id(unsigned int res_index,intps3_repository_read_vuart_av_port(unsignedint*port);intps3_repository_read_vuart_sysmgr_port(unsignedint*port);+/* repository ss info */++intps3_repository_read_ss_laid(enumps3_ss_laid*laid);+#endif
Don't put file names in files. When the file gets moved, then this will
no longer be correct.
+ *
+ * udbg debug output routine via GELIC UDP broadcasts
+ * Copyright (C) 2010 Hector Martin [off-list ref]
+ * Copyright (C) 2011 Andre Heider [off-list ref]
Some of this seems to be taken from the gelic driver, so shouldn't
the copyright info from there be included here?
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ */
+
+#include <asm/io.h>
+#include <asm/udbg.h>
+#include <asm/lv1call.h>
+
+#define GELIC_BUS_ID 1
+#define GELIC_DEVICE_ID 0
+#define GELIC_DEBUG_PORT 18194
+#define GELIC_MAX_MESSAGE_SIZE 1000
+
+#define GELIC_LV1_GET_MAC_ADDRESS 1
+#define GELIC_LV1_GET_VLAN_ID 4
+#define GELIC_LV1_VLAN_TX_ETHERNET_0 2
+
+#define GELIC_DESCR_DMA_STAT_MASK 0xf0000000
+#define GELIC_DESCR_DMA_CARDOWNED 0xa0000000
+
+#define GELIC_DESCR_TX_DMA_IKE 0x00080000
+#define GELIC_DESCR_TX_DMA_NO_CHKSUM 0x00000000
+#define GELIC_DESCR_TX_DMA_FRAME_TAIL 0x00040000
+
+#define GELIC_DESCR_DMA_CMD_NO_CHKSUM (GELIC_DESCR_DMA_CARDOWNED | \
+ GELIC_DESCR_TX_DMA_IKE | \
+ GELIC_DESCR_TX_DMA_NO_CHKSUM)
+
+static u64 bus_addr;
+
+struct gelic_descr {
+ /* as defined by the hardware */
These are BE from the hardware, so should be __beXX types.
+ u32 buf_addr;
+ u32 buf_size;
+ u32 next_descr_addr;
+ u32 dmac_cmd_status;
+ u32 result_size;
+ u32 valid_size; /* all zeroes for tx */
+ u32 data_status;
+ u32 data_error; /* all zeroes for tx */
+} __attribute__((aligned(32)));
...
+static void gelic_debug_init(void)
+{
...
+ result = lv1_net_control(GELIC_BUS_ID, GELIC_DEVICE_ID,
+ GELIC_LV1_GET_VLAN_ID,
+ GELIC_LV1_VLAN_TX_ETHERNET_0, 0, 0,
+ &vlan_id, &v2);
+ if (result == 0) {
The driver implements a character and misc device, meant for the
axed OtherOS to exchange various settings with GameOS.
Since Firmware 3.21 there is no GameOS support anymore to write these
settings, so limit the driver to the OtherOS environment.
This is really a test if running on the PS3 OtherOS, so this
comment should state that.
From: Hector Martin <hidden> Date: 2011-08-04 00:08:34
On 08/04/2011 12:32 AM, Geoff Levand wrote:
We need an explanation of this change.
I actually have a hard time understanding the reason for the existing
behavior of hot-adding memory halfway through the boot process. Maybe
you can shed some light on this?
The reason for the change is that under the default GameOS LPAR, real
mode memory is 16MB which is already tight for a kernel (under certain
conditions) and runs out quickly as memory is allocated during kernel
startup. Having region1 available sooner fixes this.
Though, reviewing the code, I think I found a bug (that should already
have a chance of happening as things stand now, though this patch might
make it more likely): if storage bounce buffers or the ps3fb xdr happen
to straddle the boundary between the regions, bad things will happen
since they're not actually contiguous in LPAR space. This won't happen
right now for ps3flash or ps3fb since those are allocated early out of
bootmem, but it can currently happen for the other buffers (ps3disk,
ps3vram, etc.) AFAICT.
Maybe we should introduce a reserved or nonexistent page gap at the
beginning of region1 to ensure that nothing will ever allocate
contiguous memory across the boundary. That will probably prevent
bootmem from grabbing region1 due to the gap, so early on memory will be
tight. Can we get rid of the ps3flash and ps3fb preallocations to save
bootmem and just allocate them during device init like the other drivers
do? What is the reason for preallocating these?
--
Hector Martin (hector@marcansoft.com)
Public Key: http://www.marcansoft.com/marcan.asc
From: Hector Martin <hidden> Date: 2011-08-04 01:19:02
On 08/04/2011 12:30 AM, Geoff Levand wrote:
With this mechanism how is the address of the initrd passed to the
new kernel, in the DT?
Using the /chosen linux,initrd-{start,end} properties. The bootloader
knows about the Linux trick of sticking together bootmem and highmem and
precalculates the linux "physical" address. Yeah, that's a hack, it
should probably be done in the kernel so the bootloader doesn't have to
know or care about how Linux decides to lay out its physical address
space. Do you have any suggestion as to how we would do this sanely?
Right now early_init_dt_setup_initrd_arch in arch/powerpc/kernel/prom.c
is generic and doesn't know anything about platform specifics.
How would a kexec based bootloader work? If it's kernel were to allocate
high mem and the bootloader program uses the high mem, how could it tell
that kernel not to destroy the region on shutdown?
The current code contemplates the case where a non-kexec based
bootloader is the first stage and allocates highmem (and knows how to
tell the kernel about it), possibly followed by kexec stages that just
keep that allocation. To support a kexec bootloader as the first
bootloader using this mechanism would indeed require extra support to
tell that kernel to retain its allocation, preferably something that can
be decided from userland. Of course the current kexec bootloader
behavior where highmem isn't handed over to the child kernel will still
work.
If arch/powerpc/boot/ps3.c allocated the mem and added a DT entry
then other OSes that don't know about the Linux device tree won't
be able to use that allocated memory. Other OSes could do a
test to see if the allocation was already done. Another option
that might work is to write info into the LV1 repository then
have boot code look there for allocated hig mem.
If you're booting another OS that isn't Linux then it also has no use
for a Linux-specific ramdisk (linux,initrd-start) and thus no use for
preallocated highmem and should be booted as such (maybe make the
userland tools tell the kernel to release highmem if there's no initrd
defined).
Using the lv1 repo is an option, but does it make sense? It's even less
standard than a FDT and we'd have to put both the region1 location and
the initrd location in there (there's no point to maintaining highmem if
you aren't going to use it).
FWIW, the lv1 repo writing hypercalls are unused and undocumented.
quoted
+ if (!map.r1.size) {
+ DBG("%s:%d: no region 1, not adding memory\n",
+ __func__, __LINE__);
+ return 0;
+ }
Did you find this to be hit? Also, in the general case,
there could be more than one high mem region, but I don't
know of any current systems that do.
Probably only during debugging, but it doesn't sound like a bad idea
anyway (e.g. bootloader allocated highmem but didn't tell the kernel so
the kernel couldn't allocate it).
As for multiple regions, well, currently it only supports one and that
is hardcoded in the phys->lpar translation, so I see no point in
worrying about that now.
ACK on the other code comments.
--
Hector Martin (hector@marcansoft.com)
Public Key: http://www.marcansoft.com/marcan.asc
On Thu, Aug 4, 2011 at 02:08, Hector Martin [off-list ref] wrote:
tight. Can we get rid of the ps3flash and ps3fb preallocations to save
bootmem and just allocate them during device init like the other drivers
do? What is the reason for preallocating these?
The reason for that is to make sure the allocations will succeed.
Chances are very
slim you can allocate a contiguous 9 MiB buffer at any arbitrary time.
Gr{oetje,eeting}s,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k=
.org
In personal conversations with technical people, I call myself a hacker. Bu=
t
when I'm talking to journalists I just say "programmer" or something like t=
hat.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 -- Linus Torvalds
From: Hector Martin <hidden> Date: 2011-08-04 11:13:10
On 08/04/2011 09:05 AM, Geert Uytterhoeven wrote:
The reason for that is to make sure the allocations will succeed.
Chances are very
slim you can allocate a contiguous 9 MiB buffer at any arbitrary time.
Fair enough, but then they don't need to happen as early as they do now;
any time during kernel startup should work (as long as they aren't freed
with the drivers if they're unloaded). How about switching to
__get_free_pages and doing the allocation inside an arch_initcall or
similar?
--
Hector Martin (hector@marcansoft.com)
Public Key: http://www.marcansoft.com/marcan.asc
Hi Hector,
On 08/03/2011 05:08 PM, Hector Martin wrote:
On 08/04/2011 12:32 AM, Geoff Levand wrote:
quoted
We need an explanation of this change.
Sorry for such a terse request. What I meant was that
this is a significant change to how high mem is managed,
so the patch needs a comment explaining the change.
I actually have a hard time understanding the reason for the existing
behavior of hot-adding memory halfway through the boot process. Maybe
you can shed some light on this?
LV1 was intended to be a generic hypervisor for the Cell
processor. It was imagined that it could be used on machines
which could be running many lpars. Around the same time I
was doing the high mem support the hot plug memory support was
being developed. I thought at some point there would be
hot-unplug, which could be used to move memory between lpars.
At the present time this change make sense, since it is simpler
and more flexible.
-Geoff
From: Andre Heider <hidden> Date: 2011-08-04 16:31:57
Hi Geoff,
On Thu, Aug 4, 2011 at 12:23 AM, Geoff Levand [off-list ref] wrote:
Hi Andre,
On 08/01/2011 01:02 PM, Andre Heider wrote:
quoted
This series addresses various issues and extends support when running
in lpars like GameOS. Included are some patches from Hector Martin, whic=
h
quoted
I found useful.
Much of this is just general fixups and improvements to the existing PS3
support. =A0I think you should separate those changes out and work to get
them included, then consider others. =A0If I give some comment, then
I consider that part worth pursuing at the present time.
Sounds like a good approach to me.
I have limited time to review the patches, so it will take me a while to
get through them.
No problem at all, it will probably take some time to resolve all the
details anyway.
quoted
Patches are based on 2.6.39 since master doesn't boot with smp on my
console. =A0I wasn't able to pinpoint the cause so far (not that I tried
too hard).
I'm looking into this problem, but it will take some time.
Just for the record: I didn't mean to push ;)
Thanks,
Andre
Only PS3_SS_LAID_OTHEROS is used for anything outside ps3_setup_arch(),
so I think it makes sense to split this into two patches with one adding
just PS3_SS_LAID_OTHEROS and ps3_get_ss_laid() with a comment that
it adds the ps3_get_ss_laid routine.
Sounds reasonable, I will split that into two patches then.
Don't put file names in files. =A0When the file gets moved, then this wil=
l
no longer be correct.
quoted
+ *
+ * udbg debug output routine via GELIC UDP broadcasts
+ * Copyright (C) 2010 Hector Martin [off-list ref]
+ * Copyright (C) 2011 Andre Heider [off-list ref]
Some of this seems to be taken from the gelic driver, so shouldn't
the copyright info from there be included here?
quoted
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ */
+
+#include <asm/io.h>
+#include <asm/udbg.h>
+#include <asm/lv1call.h>
+
+#define GELIC_BUS_ID 1
+#define GELIC_DEVICE_ID 0
+#define GELIC_DEBUG_PORT 18194
+#define GELIC_MAX_MESSAGE_SIZE 1000
+
+#define GELIC_LV1_GET_MAC_ADDRESS 1
+#define GELIC_LV1_GET_VLAN_ID 4
+#define GELIC_LV1_VLAN_TX_ETHERNET_0 2
+
+#define GELIC_DESCR_DMA_STAT_MASK 0xf0000000
+#define GELIC_DESCR_DMA_CARDOWNED 0xa0000000
+
+#define GELIC_DESCR_TX_DMA_IKE 0x00080000
+#define GELIC_DESCR_TX_DMA_NO_CHKSUM 0x00000000
+#define GELIC_DESCR_TX_DMA_FRAME_TAIL 0x00040000
+
+#define GELIC_DESCR_DMA_CMD_NO_CHKSUM (GELIC_DESCR_DMA_CARDOWNED | \
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
From: Andre Heider <hidden> Date: 2011-08-04 16:40:36
On Thu, Aug 4, 2011 at 12:34 AM, Geoff Levand [off-list ref] wrote:
On 08/01/2011 01:02 PM, Andre Heider wrote:
quoted
The driver implements a character and misc device, meant for the
axed OtherOS to exchange various settings with GameOS.
Since Firmware 3.21 there is no GameOS support anymore to write these
settings, so limit the driver to the OtherOS environment.
This is really a test if running on the PS3 OtherOS, so this
comment should state that.
How would a kexec based bootloader work? If it's kernel were to allocate
high mem and the bootloader program uses the high mem, how could it tell
that kernel not to destroy the region on shutdown?
The current code contemplates the case where a non-kexec based
bootloader is the first stage and allocates highmem (and knows how to
tell the kernel about it), possibly followed by kexec stages that just
keep that allocation. To support a kexec bootloader as the first
bootloader using this mechanism would indeed require extra support to
tell that kernel to retain its allocation, preferably something that can
be decided from userland. Of course the current kexec bootloader
behavior where highmem isn't handed over to the child kernel will still
work.
quoted
If arch/powerpc/boot/ps3.c allocated the mem and added a DT entry
then other OSes that don't know about the Linux device tree won't
be able to use that allocated memory. Other OSes could do a
test to see if the allocation was already done. Another option
that might work is to write info into the LV1 repository then
have boot code look there for allocated hig mem.
If you're booting another OS that isn't Linux then it also has no use
for a Linux-specific ramdisk (linux,initrd-start) and thus no use for
preallocated highmem and should be booted as such (maybe make the
userland tools tell the kernel to release highmem if there's no initrd
defined).
This sounds complicated, user programs managing memory regions.
Also, it needs to be considered that a lot of kernels are out
there will be confused if started with high mem already allocated.
Using the lv1 repo is an option, but does it make sense? It's even less
standard than a FDT and we'd have to put both the region1 location and
the initrd location in there (there's no point to maintaining highmem if
you aren't going to use it).
FWIW, the lv1 repo writing hypercalls are unused and undocumented.
ps3flash_init() is called straight from module_init(), so it could be
called on non-PS3.
ps3_system_bus_driver_register() has the firmware_has_feature_check(),
so it will
reject non-PS3.
But if your *_init() does any processing before calling
ps3_system_bus_driver_register()
(like ps3disk_init() does, and ps3flash_init() now does due to your
patch), you have to
do the check yourself, to make sure it returns early on non-PS3.
Gr{oetje,eeting}s,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k=
.org
In personal conversations with technical people, I call myself a hacker. Bu=
t
when I'm talking to journalists I just say "programmer" or something like t=
hat.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 -- Linus Torvalds
From: Andre Heider <hidden> Date: 2011-08-06 11:50:58
On Thu, Aug 4, 2011 at 9:24 PM, Geoff Levand [off-list ref] wrote:
Also, it needs to be considered that a lot of kernels are out
there will be confused if started with high mem already allocated.
True, but is there anything we can do about that?
Isn't is okay to tell users of first stage boot loaders utilizing this
mechanism that whatever steps their boot chain contains has to support
this highmem pass over? As far as I can tell all current loaders won't
be affected by this patch.
When a user wants to chain a loader with this mechanism with
petitboot, he needs a petitboot coming with a kernel containing this
feature, and can then kexec whatever contains it too.
quoted
Using the lv1 repo is an option, but does it make sense? It's even less
standard than a FDT and we'd have to put both the region1 location and
the initrd location in there (there's no point to maintaining highmem if
you aren't going to use it).
FWIW, the lv1 repo writing hypercalls are unused and undocumented.
#92 should be named lv1_write_repository_node.
You can only modify the repo for your lpar, so:
=A0lv1_{create,write}_repository_node(n1, n2, n3, n4, v1, v2);
=A0lv1_delete_repository_node(n1, n2, n3, n4);
I tried this and it indeed works - I can pass over the highmem info
just fine using repository nodes.
If there is a chance that another OS might require this highmem pass
over then I agree that using the repository makes more sense.
I can prepare a patch for that, replacing this one. Any suggestions on
which nodes to use?
For a test run I used:
FIELD_FIRST("bi", 0),
FIELD("highmem", 0),
FIELD("address", 0),
0
and
FIELD_FIRST("bi", 0),
FIELD("highmem", 0),
FIELD("size", 0),
0
Regards,
Andre
From: Andre Heider <hidden> Date: 2011-08-06 12:28:08
On Mon, Aug 1, 2011 at 10:58 PM, Andre Heider [off-list ref] wrote:
On Mon, Aug 1, 2011 at 10:30 PM, Geert Uytterhoeven
[off-list ref] wrote:
quoted
On Mon, Aug 1, 2011 at 22:03, Andre Heider [off-list ref] wrote:
quoted
There can be only 8 regions, add a sanity check
Why can there be only 8 regions?
I believe lv1 limits it to 8? I might be mistaken here, it mostly is a
check for the patches after this one
Small follow-up:
While the repository contains ("bus", "dev", "n_regs") to describe the
actual number of regions, it also contains ("bus", "dev", "region", [
"id" | "start" | "size" ]) for always exactly 8 regions (with a value
of 0xdeadbeef for invalid regions).
I added this check for the storage drivers, which contain:
for (region_idx = 0; region_idx < dev->num_regions; region_idx++) {
...
gendisk->first_minor = devidx * PS3DISK_MINORS + region_idx;
But that limit might be raised in future hypervisor versions.
Maybe a
BUG_ON(dev->num_regions <= PS3DISK_MINORS);
is more appropriate?
ps3flash_init() is called straight from module_init(), so it could be
called on non-PS3.
ps3_system_bus_driver_register() has the firmware_has_feature_check(),
so it will
reject non-PS3.
But if your *_init() does any processing before calling
ps3_system_bus_driver_register()
(like ps3disk_init() does, and ps3flash_init() now does due to your
patch), you have to
do the check yourself, to make sure it returns early on non-PS3.
From: Andre Heider <hidden> Date: 2011-08-06 12:47:05
On Sat, Aug 6, 2011 at 2:28 PM, Andre Heider [off-list ref] wrote:
On Mon, Aug 1, 2011 at 10:58 PM, Andre Heider [off-list ref] wrote:
quoted
On Mon, Aug 1, 2011 at 10:30 PM, Geert Uytterhoeven
[off-list ref] wrote:
quoted
On Mon, Aug 1, 2011 at 22:03, Andre Heider [off-list ref] wrote:
quoted
There can be only 8 regions, add a sanity check
Why can there be only 8 regions?
I believe lv1 limits it to 8? I might be mistaken here, it mostly is a
check for the patches after this one
Small follow-up:
While the repository contains ("bus", "dev", "n_regs") to describe the
actual number of regions, it also contains ("bus", "dev", "region", [
"id" | "start" | "size" ]) for always exactly 8 regions (with a value
of 0xdeadbeef for invalid regions).
I added this check for the storage drivers, which contain:
=A0for (region_idx =3D 0; region_idx < dev->num_regions; region_idx++) {
=A0 =A0...
=A0 =A0gendisk->first_minor =3D devidx * PS3DISK_MINORS + region_idx;
But that limit might be raised in future hypervisor versions.
Maybe a
=A0BUG_ON(dev->num_regions <=3D PS3DISK_MINORS);
is more appropriate?
Of course I meant the exact opposite, heh:
=A0BUG_ON(dev->num_regions > PS3DISK_MINORS);
+ *
+ * udbg debug output routine via GELIC UDP broadcasts
+ * Copyright (C) 2010 Hector Martin [off-list ref]
+ * Copyright (C) 2011 Andre Heider [off-list ref]
Some of this seems to be taken from the gelic driver, so shouldn't
the copyright info from there be included here?
Moreover, if there is a significant amount of code duplication
between this driver and gelic, I would expect to actually share
the code instead, either by integrating the udbg code into the
gelic driver in form of netconsole support, or by moving the
common parts into a separate module.
Arnd
This series addresses various issues and extends support when running
in lpars like GameOS. Included are some patches from Hector Martin, which
I found useful.
Hi Andre,
I've looked at the entire series and support merging it into 3.2 once
the concerns from Geoff and Geert are resolved. I don't have anything
to add there.
Arnd
From: Andre Heider <hidden> Date: 2011-08-11 17:32:14
On Thu, Aug 11, 2011 at 2:13 PM, Arnd Bergmann [off-list ref] wrote:
On Thursday 04 August 2011, Geoff Levand wrote:
quoted
quoted
+ *
+ * udbg debug output routine via GELIC UDP broadcasts
+ * Copyright (C) 2010 Hector Martin [off-list ref]
+ * Copyright (C) 2011 Andre Heider [off-list ref]
Some of this seems to be taken from the gelic driver, so shouldn't
the copyright info from there be included here?
Moreover, if there is a significant amount of code duplication
between this driver and gelic, I would expect to actually share
the code instead, either by integrating the udbg code into the
gelic driver in form of netconsole support, or by moving the
common parts into a separate module.
No, thankfully there is no significant code duplication :)
It contains a few structs and defines found elsewhere, but that's
because it's not a real netdev. It just prepares the eth/ip/udp header
once for its single purpose, then uses the hypervisor to send and poll
- in contrast to the gelic driver, which reuses its irqhandler for
netconsole support.
From: Andre Heider <hidden> Date: 2011-08-11 17:34:58
On Thu, Aug 11, 2011 at 2:17 PM, Arnd Bergmann [off-list ref] wrote:
On Monday 01 August 2011, Andre Heider wrote:
quoted
This series addresses various issues and extends support when running
in lpars like GameOS. Included are some patches from Hector Martin, which
I found useful.
Hi Andre,
I've looked at the entire series and support merging it into 3.2 once
the concerns from Geoff and Geert are resolved. I don't have anything
to add there.
Hi Arnd,
thanks, I'll send the first part of v2 soon
From: Andre Heider <hidden> Date: 2011-08-11 19:31:04
This is the first part of my previous series including the discussed fixups.
I dropped the old #2 ([PS3] Get lv1 high memory region from devtree)
and replaced it with 2 new patches, now #2 and #3. The latter contains
the fixups mentioned on the old #2 thread.
Patches are based on today's Linus' tree.
Andre Heider (7):
ps3: Add helper functions to read highmem info from the repository
ps3: Get lv1 high memory region from the repository
ps3: MEMORY_HOTPLUG is not a requirement anymore
ps3: Detect the current lpar
ps3: Log the detected lpar on startup
ps3flash: Refuse to work in lpars other than OtherOS
ps3: Only prealloc the flash bounce buffer for the OtherOS lpar
Hector Martin (2):
Add udbg driver using the PS3 gelic Ethernet device
Add region 1 memory early
arch/powerpc/Kconfig.debug | 8 +
arch/powerpc/include/asm/ps3.h | 7 +
arch/powerpc/include/asm/udbg.h | 1 +
arch/powerpc/kernel/udbg.c | 2 +
arch/powerpc/platforms/ps3/Kconfig | 15 ++-
arch/powerpc/platforms/ps3/Makefile | 1 +
arch/powerpc/platforms/ps3/gelic_udbg.c | 273 +++++++++++++++++++++++++++++++
arch/powerpc/platforms/ps3/mm.c | 85 +++++------
arch/powerpc/platforms/ps3/platform.h | 7 +
arch/powerpc/platforms/ps3/repository.c | 55 ++++++
arch/powerpc/platforms/ps3/setup.c | 27 +++-
drivers/char/ps3flash.c | 7 +
drivers/net/ps3_gelic_net.c | 3 +
drivers/net/ps3_gelic_net.h | 6 +
14 files changed, 447 insertions(+), 50 deletions(-)
create mode 100644 arch/powerpc/platforms/ps3/gelic_udbg.c
--
1.7.5.4
From: Andre Heider <hidden> Date: 2011-08-11 19:31:06
An earlier step in the boot chain can preallocate the highmem region.
A boot loader doing so will place the region infos in the repository.
Provide helper functions to read the required nodes.
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/platforms/ps3/platform.h | 3 ++
arch/powerpc/platforms/ps3/repository.c | 36 +++++++++++++++++++++++++++++++
2 files changed, 39 insertions(+), 0 deletions(-)
@@ -187,6 +187,9 @@ int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size);intps3_repository_read_region_total(u64*region_total);intps3_repository_read_mm_info(u64*rm_base,u64*rm_size,u64*region_total);+intps3_repository_read_highmem_base(u64*highmem_base);+intps3_repository_read_highmem_size(u64*highmem_size);+intps3_repository_read_highmem_info(u64*highmem_base,u64*highmem_size);/* repository pme info */
From: Andre Heider <hidden> Date: 2011-08-11 19:31:07
This lets the bootloader preallocate the high lv1 region and pass its
location to the kernel through the repository. Thus, it can be used to
hold the initrd. If the region info doesn't exist, the kernel retains
the old behavior and attempts to allocate the region itself.
Based on the patch
"[PS3] Get lv1 high memory region from devtree"
from Hector Martin [off-list ref]
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/platforms/ps3/mm.c | 46 ++++++++++++++++++++++++++++++++++++--
1 files changed, 43 insertions(+), 3 deletions(-)
@@ -287,6 +296,29 @@ static void ps3_mm_region_destroy(struct mem_region *r)}}+staticintps3_mm_get_repository_highmem(structmem_region*r)+{+intresult=ps3_repository_read_highmem_info(&r->base,&r->size);++if(result)+gotozero_region;++if(!r->base||!r->size){+result=-1;+gotozero_region;+}++r->offset=r->base-map.rm.size;+DBG("%s:%d got high region from repository: %llxh %llxh\n",+__func__,__LINE__,r->base,r->size);+return0;++zero_region:+DBG("%s:%d no high region in repository...\n",__func__,__LINE__);+r->size=r->base=r->offset=0;+returnresult;+}+/***ps3_mm_add_memory-hotaddmemory*/
@@ -303,6 +335,12 @@ static int __init ps3_mm_add_memory(void)BUG_ON(!mem_init_done);+if(!map.r1.size){+DBG("%s:%d: no region 1, not adding memory\n",+__func__,__LINE__);+return0;+}+start_addr=map.rm.size;start_pfn=start_addr>>PAGE_SHIFT;nr_pages=(map.r1.size+PAGE_SIZE-1)>>PAGE_SHIFT;
@@ -1217,9 +1255,11 @@ void __init ps3_mm_init(void)BUG_ON(map.rm.base);BUG_ON(!map.rm.size);--/* arrange to do this in ps3_mm_add_memory */-ps3_mm_region_create(&map.r1,map.total-map.rm.size);+/* check if we got the highmem region from an earlier boot step */+if(ps3_mm_get_repository_highmem(&map.r1)){+/* arrange to do this in ps3_mm_add_memory */+ps3_mm_region_create(&map.r1,map.total-map.rm.size);+}/* correct map.total for the real total amount of memory we use */map.total=map.rm.size+map.r1.size;
From: Andre Heider <hidden> Date: 2011-08-11 19:31:08
From: Hector Martin <redacted>
Real mode memory can be limited and runs out quickly as memory is
allocated during kernel startup.
Having region1 available sooner fixes this.
Signed-off-by: Hector Martin <redacted>
[a.heider: Various cleanups to make checkpatch.pl happy]
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/platforms/ps3/mm.c | 75 +++++++--------------------------------
1 files changed, 13 insertions(+), 62 deletions(-)
@@ -319,57 +312,6 @@ zero_region:returnresult;}-/**-*ps3_mm_add_memory-hotaddmemory-*/--staticint__initps3_mm_add_memory(void)-{-intresult;-unsignedlongstart_addr;-unsignedlongstart_pfn;-unsignedlongnr_pages;--if(!firmware_has_feature(FW_FEATURE_PS3_LV1))-return-ENODEV;--BUG_ON(!mem_init_done);--if(!map.r1.size){-DBG("%s:%d: no region 1, not adding memory\n",-__func__,__LINE__);-return0;-}--start_addr=map.rm.size;-start_pfn=start_addr>>PAGE_SHIFT;-nr_pages=(map.r1.size+PAGE_SIZE-1)>>PAGE_SHIFT;--DBG("%s:%d: start_addr %lxh, start_pfn %lxh, nr_pages %lxh\n",-__func__,__LINE__,start_addr,start_pfn,nr_pages);--result=add_memory(0,start_addr,map.r1.size);--if(result){-pr_err("%s:%d: add_memory failed: (%d)\n",-__func__,__LINE__,result);-returnresult;-}--memblock_add(start_addr,map.r1.size);-memblock_analyze();--result=online_pages(start_pfn,nr_pages);--if(result)-pr_err("%s:%d: online_pages failed: (%d)\n",-__func__,__LINE__,result);--returnresult;-}--device_initcall(ps3_mm_add_memory);-/*============================================================================*//* dma routines *//*============================================================================*/
@@ -1256,14 +1198,23 @@ void __init ps3_mm_init(void)BUG_ON(!map.rm.size);/* check if we got the highmem region from an earlier boot step */-if(ps3_mm_get_repository_highmem(&map.r1)){-/* arrange to do this in ps3_mm_add_memory */+if(ps3_mm_get_repository_highmem(&map.r1))ps3_mm_region_create(&map.r1,map.total-map.rm.size);-}/* correct map.total for the real total amount of memory we use */map.total=map.rm.size+map.r1.size;+if(!map.r1.size){+DBG("%s:%d: no region 1, not adding memory\n",+__func__,__LINE__);+}else{+DBG("%s:%d: adding memory: start %llxh, size %llxh\n",+__func__,__LINE__,map.rm.size,map.r1.size);++memblock_add(map.rm.size,map.r1.size);+memblock_analyze();+}+DBG(" <- %s:%d\n",__func__,__LINE__);}
From: Andre Heider <hidden> Date: 2011-08-11 19:31:10
Detect it by reading the ss laid repository node, and make it
accessible via ps3_get_ss_laid().
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/include/asm/ps3.h | 6 ++++++
arch/powerpc/platforms/ps3/platform.h | 4 ++++
arch/powerpc/platforms/ps3/repository.c | 19 +++++++++++++++++++
arch/powerpc/platforms/ps3/setup.c | 9 +++++++++
4 files changed, 38 insertions(+), 0 deletions(-)
@@ -235,4 +235,8 @@ int ps3_repository_read_spu_resource_id(unsigned int res_index,intps3_repository_read_vuart_av_port(unsignedint*port);intps3_repository_read_vuart_sysmgr_port(unsignedint*port);+/* repository ss info */++intps3_repository_read_ss_laid(enumps3_ss_laid*laid);+#endif
From: Andre Heider <hidden> Date: 2011-08-11 19:31:12
The driver implements a character and misc device, meant for the
axed OtherOS to exchange various settings with GameOS.
Since Firmware 3.21 there is no support anymore to write these
settings, so test if we're running in OtherOS, and refuse to load
if that is not the case.
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/platforms/ps3/Kconfig | 2 +-
drivers/char/ps3flash.c | 7 +++++++
2 files changed, 8 insertions(+), 1 deletions(-)
From: Andre Heider <hidden> Date: 2011-08-11 19:31:13
It's only used by the ps3flash driver, which only supports the
OtherOS lpar.
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/platforms/ps3/setup.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
@@ -233,7 +233,10 @@ static void __init ps3_setup_arch(void)#endifprealloc_ps3fb_videomemory();-prealloc_ps3flash_bounce_buffer();++/* the ps3flash driver only works for OtherOS */+if(ps3_get_ss_laid()==PS3_SS_LAID_OTHEROS)+prealloc_ps3flash_bounce_buffer();ppc_md.power_save=ps3_power_save;ps3_os_area_init();
Hi,
We had some questions as to why we have this totally separate driver
from the gelic driver, so I think it worthwhile to have an
explanation of why in the commit log. Otherwise, the code looks
OK.
-Geoff
An earlier step in the boot chain can preallocate the highmem region.
A boot loader doing so will place the region infos in the repository.
Provide helper functions to read the required nodes.
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/platforms/ps3/platform.h | 3 ++
arch/powerpc/platforms/ps3/repository.c | 36 +++++++++++++++++++++++++++++++
2 files changed, 39 insertions(+), 0 deletions(-)
@@ -187,6 +187,9 @@ int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size);intps3_repository_read_region_total(u64*region_total);intps3_repository_read_mm_info(u64*rm_base,u64*rm_size,u64*region_total);+intps3_repository_read_highmem_base(u64*highmem_base);+intps3_repository_read_highmem_size(u64*highmem_size);+intps3_repository_read_highmem_info(u64*highmem_base,u64*highmem_size);
In the general case we could have multiple regions. If we
add a region arg here we can handle that if needed.
region_index would be {1..}. ps3_repository_read_highmem_info
could hold how many regions, so:
int ps3_repository_read_highmem_base(unsigned int region_index, u64 *highmem_base);
int ps3_repository_read_highmem_size(unsigned int region_index, u64 *highmem_size);
int ps3_repository_read_highmem_region(unsigned int region_index, u64 *highmem_base, u64 *highmem_size);
This lets the bootloader preallocate the high lv1 region and pass its
location to the kernel through the repository. Thus, it can be used to
hold the initrd. If the region info doesn't exist, the kernel retains
the old behavior and attempts to allocate the region itself.
Based on the patch
"[PS3] Get lv1 high memory region from devtree"
from Hector Martin [off-list ref]
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/platforms/ps3/mm.c | 46 ++++++++++++++++++++++++++++++++++++--
1 files changed, 43 insertions(+), 3 deletions(-)
@@ -287,6 +296,29 @@ static void ps3_mm_region_destroy(struct mem_region *r)}}+staticintps3_mm_get_repository_highmem(structmem_region*r)+{+intresult=ps3_repository_read_highmem_info(&r->base,&r->size);++if(result)+gotozero_region;++if(!r->base||!r->size){+result=-1;+gotozero_region;+}++r->offset=r->base-map.rm.size;+DBG("%s:%d got high region from repository: %llxh %llxh\n",+__func__,__LINE__,r->base,r->size);+return0;++zero_region:+DBG("%s:%d no high region in repository...\n",__func__,__LINE__);
Three dots implies something more is on its way. I
don't think we need them.
@@ -303,6 +335,12 @@ static int __init ps3_mm_add_memory(void) BUG_ON(!mem_init_done);+ if (!map.r1.size) {+ DBG("%s:%d: no region 1, not adding memory\n",+ __func__, __LINE__);+ return 0;+ }+ start_addr = map.rm.size; start_pfn = start_addr >> PAGE_SHIFT; nr_pages = (map.r1.size + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -1217,9 +1255,11 @@ void __init ps3_mm_init(void) BUG_ON(map.rm.base); BUG_ON(!map.rm.size);-- /* arrange to do this in ps3_mm_add_memory */- ps3_mm_region_create(&map.r1, map.total - map.rm.size);+ /* check if we got the highmem region from an earlier boot step */+ if (ps3_mm_get_repository_highmem(&map.r1)) {+ /* arrange to do this in ps3_mm_add_memory */+ ps3_mm_region_create(&map.r1, map.total - map.rm.size);+ } /* correct map.total for the real total amount of memory we use */ map.total = map.rm.size + map.r1.size;
From: Hector Martin <redacted>
Real mode memory can be limited and runs out quickly as memory is
allocated during kernel startup.
Having region1 available sooner fixes this.
Signed-off-by: Hector Martin <redacted>
[a.heider: Various cleanups to make checkpatch.pl happy]
Signed-off-by: Andre Heider <redacted>
---
arch/powerpc/platforms/ps3/mm.c | 75 +++++++--------------------------------
1 files changed, 13 insertions(+), 62 deletions(-)
This is still true, so we should keep these comments. We
are only changing the way we use the feature.
* @rm: real mode (bootmem) region
- * @r1: hotplug memory region(s)
+ * @r1: high memory region
high memory region(s)
quoted hunk
*
* ps3 addresses
* virt_addr: a cpu 'translated' effective address
@@ -223,10 +220,6 @@ void ps3_mm_vas_destroy(void) } }-/*============================================================================*/-/* memory hotplug routines */-/*============================================================================*/- /** * ps3_mm_region_create - create a memory region in the vas * @r: pointer to a struct mem_region to accept initialized values
@@ -319,57 +312,6 @@ zero_region: return result; }-/**- * ps3_mm_add_memory - hot add memory- */--static int __init ps3_mm_add_memory(void)-{- int result;- unsigned long start_addr;- unsigned long start_pfn;- unsigned long nr_pages;-- if (!firmware_has_feature(FW_FEATURE_PS3_LV1))- return -ENODEV;-- BUG_ON(!mem_init_done);-- if (!map.r1.size) {- DBG("%s:%d: no region 1, not adding memory\n",- __func__, __LINE__);- return 0;- }-- start_addr = map.rm.size;- start_pfn = start_addr >> PAGE_SHIFT;- nr_pages = (map.r1.size + PAGE_SIZE - 1) >> PAGE_SHIFT;-- DBG("%s:%d: start_addr %lxh, start_pfn %lxh, nr_pages %lxh\n",- __func__, __LINE__, start_addr, start_pfn, nr_pages);-- result = add_memory(0, start_addr, map.r1.size);-- if (result) {- pr_err("%s:%d: add_memory failed: (%d)\n",- __func__, __LINE__, result);- return result;- }-- memblock_add(start_addr, map.r1.size);- memblock_analyze();-- result = online_pages(start_pfn, nr_pages);-- if (result)- pr_err("%s:%d: online_pages failed: (%d)\n",- __func__, __LINE__, result);-- return result;-}--device_initcall(ps3_mm_add_memory);- /*============================================================================*/ /* dma routines */ /*============================================================================*/
@@ -1256,14 +1198,23 @@ void __init ps3_mm_init(void) BUG_ON(!map.rm.size); /* check if we got the highmem region from an earlier boot step */- if (ps3_mm_get_repository_highmem(&map.r1)) {- /* arrange to do this in ps3_mm_add_memory */+ if (ps3_mm_get_repository_highmem(&map.r1)) ps3_mm_region_create(&map.r1, map.total - map.rm.size);- }
This should be folded into patch #3.
/* correct map.total for the real total amount of memory we use */
map.total = map.rm.size + map.r1.size;
+ if (!map.r1.size) {
+ DBG("%s:%d: no region 1, not adding memory\n",
+ __func__, __LINE__);
+ } else {
Detect it by reading the ss laid repository node, and make it
accessible via ps3_get_ss_laid().
I'm wondering now if we even need this. It is mainly used by your
later patch 8/9 that modifies ps3flash_init() to test if we should
call ps3_system_bus_driver_register(). If we don't use
ps3_get_ss_laid() and just allow ps3_system_bus_driver_register()
to be called, would the device probe fail and have the same result
as the test?
I would prefer to not have ps3_get_ss_laid() if possible.
-Geoff
The driver implements a character and misc device, meant for the
axed OtherOS to exchange various settings with GameOS.
Since Firmware 3.21 there is no support anymore to write these
settings, so test if we're running in OtherOS, and refuse to load
if that is not the case.
Please see my comments to the v1 patch regarding this text.
In Documentation/CodingStyle I read that if [only] one branch is a
single statement then the parenthesis are OK (and even recommended) for
both branches, I guess this is for style consistency. See Chapter 3,
around line 169 on my copy. I guess the wording on that paragraph can
be made more explicit, I'll try to fix that up.
Regards,
Antonio
--
Antonio Ospite
http://ao2.it
PGP public key ID: 0x4553B001
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
In Documentation/CodingStyle I read that if [only] one branch is a
single statement then the parenthesis are OK (and even recommended) for
both branches, I guess this is for style consistency. See Chapter 3,
around line 169 on my copy. I guess the wording on that paragraph can
be made more explicit, I'll try to fix that up.
Thanks for the comments. I don't think its such an important change,
mainly for consistency of style within the PS3 files.
-Geoff
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-08-31 04:26:36
On Thu, 2011-08-11 at 19:32 +0200, Andre Heider wrote:
On Thu, Aug 11, 2011 at 2:13 PM, Arnd Bergmann [off-list ref] wrote:
quoted
On Thursday 04 August 2011, Geoff Levand wrote:
quoted
quoted
+ *
+ * udbg debug output routine via GELIC UDP broadcasts
+ * Copyright (C) 2010 Hector Martin [off-list ref]
+ * Copyright (C) 2011 Andre Heider [off-list ref]
Some of this seems to be taken from the gelic driver, so shouldn't
the copyright info from there be included here?
Moreover, if there is a significant amount of code duplication
between this driver and gelic, I would expect to actually share
the code instead, either by integrating the udbg code into the
gelic driver in form of netconsole support, or by moving the
common parts into a separate module.
No, thankfully there is no significant code duplication :)
It contains a few structs and defines found elsewhere, but that's
because it's not a real netdev. It just prepares the eth/ip/udp header
once for its single purpose, then uses the hypervisor to send and poll
- in contrast to the gelic driver, which reuses its irqhandler for
netconsole support.
Ack. As long as it's not enabled by default and understood to be what it
is, ie, a tool to debug really early boot code before a more "proper"
console is available, I have no objection. There is really no code dup,
just a couple of struct definitions and it's not a big deal.
I'll merge it.
Cheers,
Ben.
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-08-31 04:29:50
On Thu, 2011-08-11 at 21:31 +0200, Andre Heider wrote:
This is the first part of my previous series including the discussed fixups.
I dropped the old #2 ([PS3] Get lv1 high memory region from devtree)
and replaced it with 2 new patches, now #2 and #3. The latter contains
the fixups mentioned on the old #2 thread.
Just back from vacation. I like these, good stuff. I'd like to have that
in soon, can you address the remaining minor comments from Geoff ?
Cheers,
Ben.
Patches are based on today's Linus' tree.
Andre Heider (7):
ps3: Add helper functions to read highmem info from the repository
ps3: Get lv1 high memory region from the repository
ps3: MEMORY_HOTPLUG is not a requirement anymore
ps3: Detect the current lpar
ps3: Log the detected lpar on startup
ps3flash: Refuse to work in lpars other than OtherOS
ps3: Only prealloc the flash bounce buffer for the OtherOS lpar
Hector Martin (2):
Add udbg driver using the PS3 gelic Ethernet device
Add region 1 memory early
arch/powerpc/Kconfig.debug | 8 +
arch/powerpc/include/asm/ps3.h | 7 +
arch/powerpc/include/asm/udbg.h | 1 +
arch/powerpc/kernel/udbg.c | 2 +
arch/powerpc/platforms/ps3/Kconfig | 15 ++-
arch/powerpc/platforms/ps3/Makefile | 1 +
arch/powerpc/platforms/ps3/gelic_udbg.c | 273 +++++++++++++++++++++++++++++++
arch/powerpc/platforms/ps3/mm.c | 85 +++++------
arch/powerpc/platforms/ps3/platform.h | 7 +
arch/powerpc/platforms/ps3/repository.c | 55 ++++++
arch/powerpc/platforms/ps3/setup.c | 27 +++-
drivers/char/ps3flash.c | 7 +
drivers/net/ps3_gelic_net.c | 3 +
drivers/net/ps3_gelic_net.h | 6 +
14 files changed, 447 insertions(+), 50 deletions(-)
create mode 100644 arch/powerpc/platforms/ps3/gelic_udbg.c
From: Hector Martin <redacted>
Add a new udbg driver for the PS3 gelic Ehthernet device.
This driver shares only a few stucture and constant definitions with the
gelic Ethernet device driver, so is implemented as a stand-alone driver
with no dependencies on the gelic Ethernet device driver.
Signed-off-by: Hector Martin <redacted>
Signed-off-by: Andre Heider <redacted>
Signed-off-by: Geoff Levand <geoff@infradead.org>
---
arch/powerpc/Kconfig.debug | 8 +
arch/powerpc/include/asm/udbg.h | 1 +
arch/powerpc/kernel/udbg.c | 2 +
arch/powerpc/platforms/ps3/Kconfig | 12 ++
arch/powerpc/platforms/ps3/Makefile | 1 +
arch/powerpc/platforms/ps3/gelic_udbg.c | 273 +++++++++++++++++++++++++++++++
drivers/net/ps3_gelic_net.c | 3 +
drivers/net/ps3_gelic_net.h | 6 +
8 files changed, 306 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/platforms/ps3/gelic_udbg.c