Esempio n. 1
0
int cxl_of_read_afu_properties(struct cxl_afu *afu, struct device_node *np)
{
	int i, len, rc;
	char *p;
	const __be32 *prop;
	u16 device_id, vendor_id;
	u32 val = 0, class_code;

	/* Properties are read in the same order as listed in PAPR */

	if (cxl_verbose) {
		pr_info("Dump of the 'ibm,coherent-platform-function' node properties:\n");

		prop = of_get_property(np, "compatible", &len);
		i = 0;
		while (i < len) {
			p = (char *) prop + i;
			pr_info("compatible: %s\n", p);
			i += strlen(p) + 1;
		}
		read_prop_string(np, "name");
	}

	rc = read_phys_addr(np, "reg", afu);
	if (rc)
		return rc;

	rc = read_phys_addr(np, "assigned-addresses", afu);
	if (rc)
		return rc;

	if (afu->psn_phys == 0)
		afu->psa = false;
	else
		afu->psa = true;

	if (cxl_verbose) {
		read_prop_string(np, "ibm,loc-code");
		read_prop_string(np, "device_type");
	}

	read_prop_dword(np, "ibm,#processes", &afu->max_procs_virtualised);

	if (cxl_verbose) {
		read_prop_dword(np, "ibm,scratchpad-size", &val);
		read_prop_dword(np, "ibm,programmable", &val);
		read_prop_string(np, "ibm,phandle");
		read_vpd(NULL, afu);
	}

	read_prop_dword(np, "ibm,max-ints-per-process", &afu->guest->max_ints);
	afu->irqs_max = afu->guest->max_ints;

	prop = read_prop_dword(np, "ibm,min-ints-per-process", &afu->pp_irqs);
	if (prop) {
		/* One extra interrupt for the PSL interrupt is already
		 * included. Remove it now to keep only AFU interrupts and
		 * match the native case.
		 */
		afu->pp_irqs--;
	}

	if (cxl_verbose) {
		read_prop_dword(np, "ibm,max-ints", &val);
		read_prop_dword(np, "ibm,vpd-size", &val);
	}

	read_prop64_dword(np, "ibm,error-buffer-size", &afu->eb_len);
	afu->eb_offset = 0;

	if (cxl_verbose)
		read_prop_dword(np, "ibm,config-record-type", &val);

	read_prop64_dword(np, "ibm,config-record-size", &afu->crs_len);
	afu->crs_offset = 0;

	read_prop_dword(np, "ibm,#config-records", &afu->crs_num);

	if (cxl_verbose) {
		for (i = 0; i < afu->crs_num; i++) {
			rc = cxl_ops->afu_cr_read16(afu, i, PCI_DEVICE_ID,
						&device_id);
			if (!rc)
				pr_info("record %d - device-id: %#x\n",
					i, device_id);
			rc = cxl_ops->afu_cr_read16(afu, i, PCI_VENDOR_ID,
						&vendor_id);
			if (!rc)
				pr_info("record %d - vendor-id: %#x\n",
					i, vendor_id);
			rc = cxl_ops->afu_cr_read32(afu, i, PCI_CLASS_REVISION,
						&class_code);
			if (!rc) {
				class_code >>= 8;
				pr_info("record %d - class-code: %#x\n",
					i, class_code);
			}
		}

		read_prop_dword(np, "ibm,function-number", &val);
		read_prop_dword(np, "ibm,privileged-function", &val);
		read_prop_dword(np, "vendor-id", &val);
		read_prop_dword(np, "device-id", &val);
		read_prop_dword(np, "revision-id", &val);
		read_prop_dword(np, "class-code", &val);
		read_prop_dword(np, "subsystem-vendor-id", &val);
		read_prop_dword(np, "subsystem-id", &val);
	}
Esempio n. 2
0
void
cap_vpd(struct device *d)
{
  word res_addr = 0, res_len, part_pos, part_len;
  byte buf[256];
  byte tag;
  byte csum = 0;

  printf("Vital Product Data\n");
  if (verbose < 2)
    return;

  while (res_addr <= PCI_VPD_ADDR_MASK)
    {
      if (!read_vpd(d, res_addr, &tag, 1, &csum))
	break;
      if (tag & 0x80)
	{
	  if (res_addr > PCI_VPD_ADDR_MASK + 1 - 3)
	    break;
	  if (!read_vpd(d, res_addr + 1, buf, 2, &csum))
	    break;
	  res_len = buf[0] + (buf[1] << 8);
	  res_addr += 3;
	}
      else
	{
	  res_len = tag & 7;
	  tag >>= 3;
	  res_addr += 1;
	}
      if (res_len > PCI_VPD_ADDR_MASK + 1 - res_addr)
	break;

      part_pos = 0;

      switch (tag)
	{
	case 0x0f:
	  printf("\t\tEnd\n");
	  return;

	case 0x82:
	  printf("\t\tProduct Name: ");
	  while (part_pos < res_len)
	    {
	      part_len = res_len - part_pos;
	      if (part_len > sizeof(buf))
		part_len = sizeof(buf);
	      if (!read_vpd(d, res_addr + part_pos, buf, part_len, &csum))
		break;
	      print_vpd_string(buf, part_len);
	      part_pos += part_len;
	    }
	  printf("\n");
	  break;

	case 0x90:
	case 0x91:
	  printf("\t\t%s fields:\n",
		 (tag == 0x90) ? "Read-only" : "Read/write");

	  while (part_pos + 3 <= res_len)
	    {
	      word read_len;
	      const struct vpd_item *item;
	      byte id1, id2;

	      if (!read_vpd(d, res_addr + part_pos, buf, 3, &csum))
		break;
	      part_pos += 3;
	      id1 = buf[0];
	      id2 = buf[1];
	      part_len = buf[2];
	      if (part_len > res_len - part_pos)
		break;

	      /* Is this item known? */
	      for (item=vpd_items; item->id1 && item->id1 != id1 ||
				   item->id2 && item->id2 != id2; item++)
		;

	      /* Only read the first byte of the RV field because the
	       * remaining bytes are not included in the checksum. */
	      read_len = (item->format == F_RESVD) ? 1 : part_len;
	      if (!read_vpd(d, res_addr + part_pos, buf, read_len, &csum))
		break;

	      printf("\t\t\t[%c%c] %s: ", id1, id2, item->name);

	      switch (item->format)
	        {
		case F_TEXT:
		  print_vpd_string(buf, part_len);
		  printf("\n");
		  break;
		case F_BINARY:
		  print_vpd_binary(buf, part_len);
		  printf("\n");
		  break;
		case F_RESVD:
		  printf("checksum %s, %d byte(s) reserved\n", csum ? "bad" : "good", part_len - 1);
		  break;
		case F_RDWR:
		  printf("%d byte(s) free\n", part_len);
		  break;
		}

	      part_pos += part_len;
	    }
	  break;

	default:
	  printf("\t\tUnknown %s resource type %02x, will not decode more.\n",
		 (tag & 0x80) ? "large" : "small", tag & ~0x80);
	  return;
	}

      res_addr += res_len;
    }

  if (res_addr == 0)
    printf("\t\tNot readable\n");
  else
    printf("\t\tNo end tag found\n");
}