xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] VT-d: make scope parsing code type safe
@ 2012-11-28 14:32 Jan Beulich
  2012-11-28 15:51 ` Keir Fraser
  2012-11-29  0:53 ` Zhang, Xiantao
  0 siblings, 2 replies; 3+ messages in thread
From: Jan Beulich @ 2012-11-28 14:32 UTC (permalink / raw)
  To: xen-devel; +Cc: xiantao.zhang

[-- Attachment #1: Type: text/plain, Size: 4728 bytes --]

Rather than requiring the scopes to be the first members of their
respective structures (so that casts can be used to switch between the
different views), properly use types and container_of().

Signed-off-by: Jan Beulich <jbeulich@suse.com>

--- a/xen/drivers/passthrough/vtd/dmar.c
+++ b/xen/drivers/passthrough/vtd/dmar.c
@@ -304,13 +304,15 @@ static int __init scope_device_count(con
 
 
 static int __init acpi_parse_dev_scope(
-    const void *start, const void *end, void *acpi_entry, int type, u16 seg)
+    const void *start, const void *end, struct dmar_scope *scope,
+    int type, u16 seg)
 {
-    struct dmar_scope *scope = acpi_entry;
     struct acpi_ioapic_unit *acpi_ioapic_unit;
     const struct acpi_dmar_device_scope *acpi_scope;
     u16 bus, sub_bus, sec_bus;
     const struct acpi_dmar_pci_path *path;
+    struct acpi_drhd_unit *drhd = type == DMAR_TYPE ?
+        container_of(scope, struct acpi_drhd_unit, scope) : NULL;
     int depth, cnt, didx = 0;
 
     if ( (cnt = scope_device_count(start, end)) < 0 )
@@ -359,9 +361,8 @@ static int __init acpi_parse_dev_scope(
                 dprintk(VTDPREFIX, " MSI HPET: %04x:%02x:%02x.%u\n",
                         seg, bus, path->dev, path->fn);
 
-            if ( type == DMAR_TYPE )
+            if ( drhd )
             {
-                struct acpi_drhd_unit *drhd = acpi_entry;
                 struct acpi_hpet_unit *acpi_hpet_unit;
 
                 acpi_hpet_unit = xmalloc(struct acpi_hpet_unit);
@@ -381,10 +382,8 @@ static int __init acpi_parse_dev_scope(
                 dprintk(VTDPREFIX, " endpoint: %04x:%02x:%02x.%u\n",
                         seg, bus, path->dev, path->fn);
 
-            if ( type == DMAR_TYPE )
+            if ( drhd )
             {
-                struct acpi_drhd_unit *drhd = acpi_entry;
-
                 if ( (seg == 0) && (bus == 0) && (path->dev == 2) &&
                      (path->fn == 0) )
                     igd_drhd_address = drhd->address;
@@ -397,9 +396,8 @@ static int __init acpi_parse_dev_scope(
                 dprintk(VTDPREFIX, " IOAPIC: %04x:%02x:%02x.%u\n",
                         seg, bus, path->dev, path->fn);
 
-            if ( type == DMAR_TYPE )
+            if ( drhd )
             {
-                struct acpi_drhd_unit *drhd = acpi_entry;
                 acpi_ioapic_unit = xmalloc(struct acpi_ioapic_unit);
                 if ( !acpi_ioapic_unit )
                     return -ENOMEM;
@@ -463,7 +461,7 @@ acpi_parse_one_drhd(struct acpi_dmar_hea
     dev_scope_start = (void *)(drhd + 1);
     dev_scope_end = ((void *)drhd) + header->length;
     ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
-                               dmaru, DMAR_TYPE, drhd->segment);
+                               &dmaru->scope, DMAR_TYPE, drhd->segment);
 
     if ( dmaru->include_all )
     {
@@ -590,7 +588,7 @@ acpi_parse_one_rmrr(struct acpi_dmar_hea
     dev_scope_start = (void *)(rmrr + 1);
     dev_scope_end   = ((void *)rmrr) + header->length;
     ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
-                               rmrru, RMRR_TYPE, rmrr->segment);
+                               &rmrru->scope, RMRR_TYPE, rmrr->segment);
 
     if ( ret || (rmrru->scope.devices_cnt == 0) )
         xfree(rmrru);
@@ -683,7 +681,7 @@ acpi_parse_one_atsr(struct acpi_dmar_hea
         dev_scope_start = (void *)(atsr + 1);
         dev_scope_end   = ((void *)atsr) + header->length;
         ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
-                                   atsru, ATSR_TYPE, atsr->segment);
+                                   &atsru->scope, ATSR_TYPE, atsr->segment);
     }
     else
     {
--- a/xen/drivers/passthrough/vtd/dmar.h
+++ b/xen/drivers/passthrough/vtd/dmar.h
@@ -59,7 +59,7 @@ struct dmar_scope {
 };
 
 struct acpi_drhd_unit {
-    struct dmar_scope scope;            /* must be first member of struct */
+    struct dmar_scope scope;
     struct list_head list;
     u64    address;                     /* register base address of the unit */
     u16    segment;
@@ -70,7 +70,7 @@ struct acpi_drhd_unit {
 };
 
 struct acpi_rmrr_unit {
-    struct dmar_scope scope;            /* must be first member of struct */
+    struct dmar_scope scope;
     struct list_head list;
     u64    base_address;
     u64    end_address;
@@ -79,7 +79,7 @@ struct acpi_rmrr_unit {
 };
 
 struct acpi_atsr_unit {
-    struct dmar_scope scope;            /* must be first member of struct */
+    struct dmar_scope scope;
     struct list_head list;
     u16    segment;
     u8     all_ports:1;



[-- Attachment #2: VT-d-scope-types.patch --]
[-- Type: text/plain, Size: 4767 bytes --]

VT-d: make scope parsing code type safe

Rather than requiring the scopes to be the first members of their
respective structures (so that casts can be used to switch between the
different views), properly use types and container_of().

Signed-off-by: Jan Beulich <jbeulich@suse.com>

--- a/xen/drivers/passthrough/vtd/dmar.c
+++ b/xen/drivers/passthrough/vtd/dmar.c
@@ -304,13 +304,15 @@ static int __init scope_device_count(con
 
 
 static int __init acpi_parse_dev_scope(
-    const void *start, const void *end, void *acpi_entry, int type, u16 seg)
+    const void *start, const void *end, struct dmar_scope *scope,
+    int type, u16 seg)
 {
-    struct dmar_scope *scope = acpi_entry;
     struct acpi_ioapic_unit *acpi_ioapic_unit;
     const struct acpi_dmar_device_scope *acpi_scope;
     u16 bus, sub_bus, sec_bus;
     const struct acpi_dmar_pci_path *path;
+    struct acpi_drhd_unit *drhd = type == DMAR_TYPE ?
+        container_of(scope, struct acpi_drhd_unit, scope) : NULL;
     int depth, cnt, didx = 0;
 
     if ( (cnt = scope_device_count(start, end)) < 0 )
@@ -359,9 +361,8 @@ static int __init acpi_parse_dev_scope(
                 dprintk(VTDPREFIX, " MSI HPET: %04x:%02x:%02x.%u\n",
                         seg, bus, path->dev, path->fn);
 
-            if ( type == DMAR_TYPE )
+            if ( drhd )
             {
-                struct acpi_drhd_unit *drhd = acpi_entry;
                 struct acpi_hpet_unit *acpi_hpet_unit;
 
                 acpi_hpet_unit = xmalloc(struct acpi_hpet_unit);
@@ -381,10 +382,8 @@ static int __init acpi_parse_dev_scope(
                 dprintk(VTDPREFIX, " endpoint: %04x:%02x:%02x.%u\n",
                         seg, bus, path->dev, path->fn);
 
-            if ( type == DMAR_TYPE )
+            if ( drhd )
             {
-                struct acpi_drhd_unit *drhd = acpi_entry;
-
                 if ( (seg == 0) && (bus == 0) && (path->dev == 2) &&
                      (path->fn == 0) )
                     igd_drhd_address = drhd->address;
@@ -397,9 +396,8 @@ static int __init acpi_parse_dev_scope(
                 dprintk(VTDPREFIX, " IOAPIC: %04x:%02x:%02x.%u\n",
                         seg, bus, path->dev, path->fn);
 
-            if ( type == DMAR_TYPE )
+            if ( drhd )
             {
-                struct acpi_drhd_unit *drhd = acpi_entry;
                 acpi_ioapic_unit = xmalloc(struct acpi_ioapic_unit);
                 if ( !acpi_ioapic_unit )
                     return -ENOMEM;
@@ -463,7 +461,7 @@ acpi_parse_one_drhd(struct acpi_dmar_hea
     dev_scope_start = (void *)(drhd + 1);
     dev_scope_end = ((void *)drhd) + header->length;
     ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
-                               dmaru, DMAR_TYPE, drhd->segment);
+                               &dmaru->scope, DMAR_TYPE, drhd->segment);
 
     if ( dmaru->include_all )
     {
@@ -590,7 +588,7 @@ acpi_parse_one_rmrr(struct acpi_dmar_hea
     dev_scope_start = (void *)(rmrr + 1);
     dev_scope_end   = ((void *)rmrr) + header->length;
     ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
-                               rmrru, RMRR_TYPE, rmrr->segment);
+                               &rmrru->scope, RMRR_TYPE, rmrr->segment);
 
     if ( ret || (rmrru->scope.devices_cnt == 0) )
         xfree(rmrru);
@@ -683,7 +681,7 @@ acpi_parse_one_atsr(struct acpi_dmar_hea
         dev_scope_start = (void *)(atsr + 1);
         dev_scope_end   = ((void *)atsr) + header->length;
         ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
-                                   atsru, ATSR_TYPE, atsr->segment);
+                                   &atsru->scope, ATSR_TYPE, atsr->segment);
     }
     else
     {
--- a/xen/drivers/passthrough/vtd/dmar.h
+++ b/xen/drivers/passthrough/vtd/dmar.h
@@ -59,7 +59,7 @@ struct dmar_scope {
 };
 
 struct acpi_drhd_unit {
-    struct dmar_scope scope;            /* must be first member of struct */
+    struct dmar_scope scope;
     struct list_head list;
     u64    address;                     /* register base address of the unit */
     u16    segment;
@@ -70,7 +70,7 @@ struct acpi_drhd_unit {
 };
 
 struct acpi_rmrr_unit {
-    struct dmar_scope scope;            /* must be first member of struct */
+    struct dmar_scope scope;
     struct list_head list;
     u64    base_address;
     u64    end_address;
@@ -79,7 +79,7 @@ struct acpi_rmrr_unit {
 };
 
 struct acpi_atsr_unit {
-    struct dmar_scope scope;            /* must be first member of struct */
+    struct dmar_scope scope;
     struct list_head list;
     u16    segment;
     u8     all_ports:1;

[-- Attachment #3: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] VT-d: make scope parsing code type safe
  2012-11-28 14:32 [PATCH] VT-d: make scope parsing code type safe Jan Beulich
@ 2012-11-28 15:51 ` Keir Fraser
  2012-11-29  0:53 ` Zhang, Xiantao
  1 sibling, 0 replies; 3+ messages in thread
From: Keir Fraser @ 2012-11-28 15:51 UTC (permalink / raw)
  To: Jan Beulich, xen-devel; +Cc: xiantao.zhang

On 28/11/2012 14:32, "Jan Beulich" <JBeulich@suse.com> wrote:

> Rather than requiring the scopes to be the first members of their
> respective structures (so that casts can be used to switch between the
> different views), properly use types and container_of().
> 
> Signed-off-by: Jan Beulich <jbeulich@suse.com>

Definitely an improvement.

Acked-by: Keir Fraser <keir@xen.org>

> --- a/xen/drivers/passthrough/vtd/dmar.c
> +++ b/xen/drivers/passthrough/vtd/dmar.c
> @@ -304,13 +304,15 @@ static int __init scope_device_count(con
>  
>  
>  static int __init acpi_parse_dev_scope(
> -    const void *start, const void *end, void *acpi_entry, int type, u16 seg)
> +    const void *start, const void *end, struct dmar_scope *scope,
> +    int type, u16 seg)
>  {
> -    struct dmar_scope *scope = acpi_entry;
>      struct acpi_ioapic_unit *acpi_ioapic_unit;
>      const struct acpi_dmar_device_scope *acpi_scope;
>      u16 bus, sub_bus, sec_bus;
>      const struct acpi_dmar_pci_path *path;
> +    struct acpi_drhd_unit *drhd = type == DMAR_TYPE ?
> +        container_of(scope, struct acpi_drhd_unit, scope) : NULL;
>      int depth, cnt, didx = 0;
>  
>      if ( (cnt = scope_device_count(start, end)) < 0 )
> @@ -359,9 +361,8 @@ static int __init acpi_parse_dev_scope(
>                  dprintk(VTDPREFIX, " MSI HPET: %04x:%02x:%02x.%u\n",
>                          seg, bus, path->dev, path->fn);
>  
> -            if ( type == DMAR_TYPE )
> +            if ( drhd )
>              {
> -                struct acpi_drhd_unit *drhd = acpi_entry;
>                  struct acpi_hpet_unit *acpi_hpet_unit;
>  
>                  acpi_hpet_unit = xmalloc(struct acpi_hpet_unit);
> @@ -381,10 +382,8 @@ static int __init acpi_parse_dev_scope(
>                  dprintk(VTDPREFIX, " endpoint: %04x:%02x:%02x.%u\n",
>                          seg, bus, path->dev, path->fn);
>  
> -            if ( type == DMAR_TYPE )
> +            if ( drhd )
>              {
> -                struct acpi_drhd_unit *drhd = acpi_entry;
> -
>                  if ( (seg == 0) && (bus == 0) && (path->dev == 2) &&
>                       (path->fn == 0) )
>                      igd_drhd_address = drhd->address;
> @@ -397,9 +396,8 @@ static int __init acpi_parse_dev_scope(
>                  dprintk(VTDPREFIX, " IOAPIC: %04x:%02x:%02x.%u\n",
>                          seg, bus, path->dev, path->fn);
>  
> -            if ( type == DMAR_TYPE )
> +            if ( drhd )
>              {
> -                struct acpi_drhd_unit *drhd = acpi_entry;
>                  acpi_ioapic_unit = xmalloc(struct acpi_ioapic_unit);
>                  if ( !acpi_ioapic_unit )
>                      return -ENOMEM;
> @@ -463,7 +461,7 @@ acpi_parse_one_drhd(struct acpi_dmar_hea
>      dev_scope_start = (void *)(drhd + 1);
>      dev_scope_end = ((void *)drhd) + header->length;
>      ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
> -                               dmaru, DMAR_TYPE, drhd->segment);
> +                               &dmaru->scope, DMAR_TYPE, drhd->segment);
>  
>      if ( dmaru->include_all )
>      {
> @@ -590,7 +588,7 @@ acpi_parse_one_rmrr(struct acpi_dmar_hea
>      dev_scope_start = (void *)(rmrr + 1);
>      dev_scope_end   = ((void *)rmrr) + header->length;
>      ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
> -                               rmrru, RMRR_TYPE, rmrr->segment);
> +                               &rmrru->scope, RMRR_TYPE, rmrr->segment);
>  
>      if ( ret || (rmrru->scope.devices_cnt == 0) )
>          xfree(rmrru);
> @@ -683,7 +681,7 @@ acpi_parse_one_atsr(struct acpi_dmar_hea
>          dev_scope_start = (void *)(atsr + 1);
>          dev_scope_end   = ((void *)atsr) + header->length;
>          ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
> -                                   atsru, ATSR_TYPE, atsr->segment);
> +                                   &atsru->scope, ATSR_TYPE, atsr->segment);
>      }
>      else
>      {
> --- a/xen/drivers/passthrough/vtd/dmar.h
> +++ b/xen/drivers/passthrough/vtd/dmar.h
> @@ -59,7 +59,7 @@ struct dmar_scope {
>  };
>  
>  struct acpi_drhd_unit {
> -    struct dmar_scope scope;            /* must be first member of struct */
> +    struct dmar_scope scope;
>      struct list_head list;
>      u64    address;                     /* register base address of the unit
> */
>      u16    segment;
> @@ -70,7 +70,7 @@ struct acpi_drhd_unit {
>  };
>  
>  struct acpi_rmrr_unit {
> -    struct dmar_scope scope;            /* must be first member of struct */
> +    struct dmar_scope scope;
>      struct list_head list;
>      u64    base_address;
>      u64    end_address;
> @@ -79,7 +79,7 @@ struct acpi_rmrr_unit {
>  };
>  
>  struct acpi_atsr_unit {
> -    struct dmar_scope scope;            /* must be first member of struct */
> +    struct dmar_scope scope;
>      struct list_head list;
>      u16    segment;
>      u8     all_ports:1;
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] VT-d: make scope parsing code type safe
  2012-11-28 14:32 [PATCH] VT-d: make scope parsing code type safe Jan Beulich
  2012-11-28 15:51 ` Keir Fraser
@ 2012-11-29  0:53 ` Zhang, Xiantao
  1 sibling, 0 replies; 3+ messages in thread
From: Zhang, Xiantao @ 2012-11-29  0:53 UTC (permalink / raw)
  To: Jan Beulich, xen-devel; +Cc: Zhang, Xiantao

Thanks!
Acked-by Xiantao Zhang <xiantao.zhang@intel.com>

> -----Original Message-----
> From: Jan Beulich [mailto:JBeulich@suse.com]
> Sent: Wednesday, November 28, 2012 10:33 PM
> To: xen-devel
> Cc: Zhang, Xiantao
> Subject: [PATCH] VT-d: make scope parsing code type safe
> 
> Rather than requiring the scopes to be the first members of their respective
> structures (so that casts can be used to switch between the different views),
> properly use types and container_of().
> 
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> 
> --- a/xen/drivers/passthrough/vtd/dmar.c
> +++ b/xen/drivers/passthrough/vtd/dmar.c
> @@ -304,13 +304,15 @@ static int __init scope_device_count(con
> 
> 
>  static int __init acpi_parse_dev_scope(
> -    const void *start, const void *end, void *acpi_entry, int type, u16 seg)
> +    const void *start, const void *end, struct dmar_scope *scope,
> +    int type, u16 seg)
>  {
> -    struct dmar_scope *scope = acpi_entry;
>      struct acpi_ioapic_unit *acpi_ioapic_unit;
>      const struct acpi_dmar_device_scope *acpi_scope;
>      u16 bus, sub_bus, sec_bus;
>      const struct acpi_dmar_pci_path *path;
> +    struct acpi_drhd_unit *drhd = type == DMAR_TYPE ?
> +        container_of(scope, struct acpi_drhd_unit, scope) : NULL;
>      int depth, cnt, didx = 0;
> 
>      if ( (cnt = scope_device_count(start, end)) < 0 ) @@ -359,9 +361,8 @@
> static int __init acpi_parse_dev_scope(
>                  dprintk(VTDPREFIX, " MSI HPET: %04x:%02x:%02x.%u\n",
>                          seg, bus, path->dev, path->fn);
> 
> -            if ( type == DMAR_TYPE )
> +            if ( drhd )
>              {
> -                struct acpi_drhd_unit *drhd = acpi_entry;
>                  struct acpi_hpet_unit *acpi_hpet_unit;
> 
>                  acpi_hpet_unit = xmalloc(struct acpi_hpet_unit); @@ -381,10 +382,8
> @@ static int __init acpi_parse_dev_scope(
>                  dprintk(VTDPREFIX, " endpoint: %04x:%02x:%02x.%u\n",
>                          seg, bus, path->dev, path->fn);
> 
> -            if ( type == DMAR_TYPE )
> +            if ( drhd )
>              {
> -                struct acpi_drhd_unit *drhd = acpi_entry;
> -
>                  if ( (seg == 0) && (bus == 0) && (path->dev == 2) &&
>                       (path->fn == 0) )
>                      igd_drhd_address = drhd->address; @@ -397,9 +396,8 @@ static
> int __init acpi_parse_dev_scope(
>                  dprintk(VTDPREFIX, " IOAPIC: %04x:%02x:%02x.%u\n",
>                          seg, bus, path->dev, path->fn);
> 
> -            if ( type == DMAR_TYPE )
> +            if ( drhd )
>              {
> -                struct acpi_drhd_unit *drhd = acpi_entry;
>                  acpi_ioapic_unit = xmalloc(struct acpi_ioapic_unit);
>                  if ( !acpi_ioapic_unit )
>                      return -ENOMEM;
> @@ -463,7 +461,7 @@ acpi_parse_one_drhd(struct acpi_dmar_hea
>      dev_scope_start = (void *)(drhd + 1);
>      dev_scope_end = ((void *)drhd) + header->length;
>      ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
> -                               dmaru, DMAR_TYPE, drhd->segment);
> +                               &dmaru->scope, DMAR_TYPE,
> + drhd->segment);
> 
>      if ( dmaru->include_all )
>      {
> @@ -590,7 +588,7 @@ acpi_parse_one_rmrr(struct acpi_dmar_hea
>      dev_scope_start = (void *)(rmrr + 1);
>      dev_scope_end   = ((void *)rmrr) + header->length;
>      ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
> -                               rmrru, RMRR_TYPE, rmrr->segment);
> +                               &rmrru->scope, RMRR_TYPE,
> + rmrr->segment);
> 
>      if ( ret || (rmrru->scope.devices_cnt == 0) )
>          xfree(rmrru);
> @@ -683,7 +681,7 @@ acpi_parse_one_atsr(struct acpi_dmar_hea
>          dev_scope_start = (void *)(atsr + 1);
>          dev_scope_end   = ((void *)atsr) + header->length;
>          ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
> -                                   atsru, ATSR_TYPE, atsr->segment);
> +                                   &atsru->scope, ATSR_TYPE,
> + atsr->segment);
>      }
>      else
>      {
> --- a/xen/drivers/passthrough/vtd/dmar.h
> +++ b/xen/drivers/passthrough/vtd/dmar.h
> @@ -59,7 +59,7 @@ struct dmar_scope {
>  };
> 
>  struct acpi_drhd_unit {
> -    struct dmar_scope scope;            /* must be first member of struct */
> +    struct dmar_scope scope;
>      struct list_head list;
>      u64    address;                     /* register base address of the unit */
>      u16    segment;
> @@ -70,7 +70,7 @@ struct acpi_drhd_unit {  };
> 
>  struct acpi_rmrr_unit {
> -    struct dmar_scope scope;            /* must be first member of struct */
> +    struct dmar_scope scope;
>      struct list_head list;
>      u64    base_address;
>      u64    end_address;
> @@ -79,7 +79,7 @@ struct acpi_rmrr_unit {  };
> 
>  struct acpi_atsr_unit {
> -    struct dmar_scope scope;            /* must be first member of struct */
> +    struct dmar_scope scope;
>      struct list_head list;
>      u16    segment;
>      u8     all_ports:1;
> 

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2012-11-29  0:53 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-11-28 14:32 [PATCH] VT-d: make scope parsing code type safe Jan Beulich
2012-11-28 15:51 ` Keir Fraser
2012-11-29  0:53 ` Zhang, Xiantao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).