root/drivers/fsi/fsi-occ.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. occ_open
  2. occ_read
  3. occ_write
  4. occ_release
  5. occ_verify_checksum
  6. occ_getsram
  7. occ_putsram
  8. occ_trigger_attn
  9. fsi_occ_submit
  10. occ_unregister_child
  11. occ_probe
  12. occ_remove
  13. occ_init
  14. occ_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 
   3 #include <linux/device.h>
   4 #include <linux/err.h>
   5 #include <linux/errno.h>
   6 #include <linux/fs.h>
   7 #include <linux/fsi-sbefifo.h>
   8 #include <linux/gfp.h>
   9 #include <linux/idr.h>
  10 #include <linux/kernel.h>
  11 #include <linux/list.h>
  12 #include <linux/miscdevice.h>
  13 #include <linux/module.h>
  14 #include <linux/mutex.h>
  15 #include <linux/fsi-occ.h>
  16 #include <linux/of.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/sched.h>
  19 #include <linux/slab.h>
  20 #include <linux/uaccess.h>
  21 #include <asm/unaligned.h>
  22 
  23 #define OCC_SRAM_BYTES          4096
  24 #define OCC_CMD_DATA_BYTES      4090
  25 #define OCC_RESP_DATA_BYTES     4089
  26 
  27 #define OCC_SRAM_CMD_ADDR       0xFFFBE000
  28 #define OCC_SRAM_RSP_ADDR       0xFFFBF000
  29 
  30 /*
  31  * Assume we don't have much FFDC, if we do we'll overflow and
  32  * fail the command. This needs to be big enough for simple
  33  * commands as well.
  34  */
  35 #define OCC_SBE_STATUS_WORDS    32
  36 
  37 #define OCC_TIMEOUT_MS          1000
  38 #define OCC_CMD_IN_PRG_WAIT_MS  50
  39 
  40 struct occ {
  41         struct device *dev;
  42         struct device *sbefifo;
  43         char name[32];
  44         int idx;
  45         struct miscdevice mdev;
  46         struct mutex occ_lock;
  47 };
  48 
  49 #define to_occ(x)       container_of((x), struct occ, mdev)
  50 
  51 struct occ_response {
  52         u8 seq_no;
  53         u8 cmd_type;
  54         u8 return_status;
  55         __be16 data_length;
  56         u8 data[OCC_RESP_DATA_BYTES + 2];       /* two bytes checksum */
  57 } __packed;
  58 
  59 struct occ_client {
  60         struct occ *occ;
  61         struct mutex lock;
  62         size_t data_size;
  63         size_t read_offset;
  64         u8 *buffer;
  65 };
  66 
  67 #define to_client(x)    container_of((x), struct occ_client, xfr)
  68 
  69 static DEFINE_IDA(occ_ida);
  70 
  71 static int occ_open(struct inode *inode, struct file *file)
  72 {
  73         struct occ_client *client = kzalloc(sizeof(*client), GFP_KERNEL);
  74         struct miscdevice *mdev = file->private_data;
  75         struct occ *occ = to_occ(mdev);
  76 
  77         if (!client)
  78                 return -ENOMEM;
  79 
  80         client->buffer = (u8 *)__get_free_page(GFP_KERNEL);
  81         if (!client->buffer) {
  82                 kfree(client);
  83                 return -ENOMEM;
  84         }
  85 
  86         client->occ = occ;
  87         mutex_init(&client->lock);
  88         file->private_data = client;
  89 
  90         /* We allocate a 1-page buffer, make sure it all fits */
  91         BUILD_BUG_ON((OCC_CMD_DATA_BYTES + 3) > PAGE_SIZE);
  92         BUILD_BUG_ON((OCC_RESP_DATA_BYTES + 7) > PAGE_SIZE);
  93 
  94         return 0;
  95 }
  96 
  97 static ssize_t occ_read(struct file *file, char __user *buf, size_t len,
  98                         loff_t *offset)
  99 {
 100         struct occ_client *client = file->private_data;
 101         ssize_t rc = 0;
 102 
 103         if (!client)
 104                 return -ENODEV;
 105 
 106         if (len > OCC_SRAM_BYTES)
 107                 return -EINVAL;
 108 
 109         mutex_lock(&client->lock);
 110 
 111         /* This should not be possible ... */
 112         if (WARN_ON_ONCE(client->read_offset > client->data_size)) {
 113                 rc = -EIO;
 114                 goto done;
 115         }
 116 
 117         /* Grab how much data we have to read */
 118         rc = min(len, client->data_size - client->read_offset);
 119         if (copy_to_user(buf, client->buffer + client->read_offset, rc))
 120                 rc = -EFAULT;
 121         else
 122                 client->read_offset += rc;
 123 
 124  done:
 125         mutex_unlock(&client->lock);
 126 
 127         return rc;
 128 }
 129 
 130 static ssize_t occ_write(struct file *file, const char __user *buf,
 131                          size_t len, loff_t *offset)
 132 {
 133         struct occ_client *client = file->private_data;
 134         size_t rlen, data_length;
 135         u16 checksum = 0;
 136         ssize_t rc, i;
 137         u8 *cmd;
 138 
 139         if (!client)
 140                 return -ENODEV;
 141 
 142         if (len > (OCC_CMD_DATA_BYTES + 3) || len < 3)
 143                 return -EINVAL;
 144 
 145         mutex_lock(&client->lock);
 146 
 147         /* Construct the command */
 148         cmd = client->buffer;
 149 
 150         /* Sequence number (we could increment and compare with response) */
 151         cmd[0] = 1;
 152 
 153         /*
 154          * Copy the user command (assume user data follows the occ command
 155          * format)
 156          * byte 0: command type
 157          * bytes 1-2: data length (msb first)
 158          * bytes 3-n: data
 159          */
 160         if (copy_from_user(&cmd[1], buf, len)) {
 161                 rc = -EFAULT;
 162                 goto done;
 163         }
 164 
 165         /* Extract data length */
 166         data_length = (cmd[2] << 8) + cmd[3];
 167         if (data_length > OCC_CMD_DATA_BYTES) {
 168                 rc = -EINVAL;
 169                 goto done;
 170         }
 171 
 172         /* Calculate checksum */
 173         for (i = 0; i < data_length + 4; ++i)
 174                 checksum += cmd[i];
 175 
 176         cmd[data_length + 4] = checksum >> 8;
 177         cmd[data_length + 5] = checksum & 0xFF;
 178 
 179         /* Submit command */
 180         rlen = PAGE_SIZE;
 181         rc = fsi_occ_submit(client->occ->dev, cmd, data_length + 6, cmd,
 182                             &rlen);
 183         if (rc)
 184                 goto done;
 185 
 186         /* Set read tracking data */
 187         client->data_size = rlen;
 188         client->read_offset = 0;
 189 
 190         /* Done */
 191         rc = len;
 192 
 193  done:
 194         mutex_unlock(&client->lock);
 195 
 196         return rc;
 197 }
 198 
 199 static int occ_release(struct inode *inode, struct file *file)
 200 {
 201         struct occ_client *client = file->private_data;
 202 
 203         free_page((unsigned long)client->buffer);
 204         kfree(client);
 205 
 206         return 0;
 207 }
 208 
 209 static const struct file_operations occ_fops = {
 210         .owner = THIS_MODULE,
 211         .open = occ_open,
 212         .read = occ_read,
 213         .write = occ_write,
 214         .release = occ_release,
 215 };
 216 
 217 static int occ_verify_checksum(struct occ_response *resp, u16 data_length)
 218 {
 219         /* Fetch the two bytes after the data for the checksum. */
 220         u16 checksum_resp = get_unaligned_be16(&resp->data[data_length]);
 221         u16 checksum;
 222         u16 i;
 223 
 224         checksum = resp->seq_no;
 225         checksum += resp->cmd_type;
 226         checksum += resp->return_status;
 227         checksum += (data_length >> 8) + (data_length & 0xFF);
 228 
 229         for (i = 0; i < data_length; ++i)
 230                 checksum += resp->data[i];
 231 
 232         if (checksum != checksum_resp)
 233                 return -EBADMSG;
 234 
 235         return 0;
 236 }
 237 
 238 static int occ_getsram(struct occ *occ, u32 address, void *data, ssize_t len)
 239 {
 240         u32 data_len = ((len + 7) / 8) * 8;     /* must be multiples of 8 B */
 241         size_t resp_len, resp_data_len;
 242         __be32 *resp, cmd[5];
 243         int rc;
 244 
 245         /*
 246          * Magic sequence to do SBE getsram command. SBE will fetch data from
 247          * specified SRAM address.
 248          */
 249         cmd[0] = cpu_to_be32(0x5);
 250         cmd[1] = cpu_to_be32(SBEFIFO_CMD_GET_OCC_SRAM);
 251         cmd[2] = cpu_to_be32(1);
 252         cmd[3] = cpu_to_be32(address);
 253         cmd[4] = cpu_to_be32(data_len);
 254 
 255         resp_len = (data_len >> 2) + OCC_SBE_STATUS_WORDS;
 256         resp = kzalloc(resp_len << 2, GFP_KERNEL);
 257         if (!resp)
 258                 return -ENOMEM;
 259 
 260         rc = sbefifo_submit(occ->sbefifo, cmd, 5, resp, &resp_len);
 261         if (rc)
 262                 goto free;
 263 
 264         rc = sbefifo_parse_status(occ->sbefifo, SBEFIFO_CMD_GET_OCC_SRAM,
 265                                   resp, resp_len, &resp_len);
 266         if (rc)
 267                 goto free;
 268 
 269         resp_data_len = be32_to_cpu(resp[resp_len - 1]);
 270         if (resp_data_len != data_len) {
 271                 dev_err(occ->dev, "SRAM read expected %d bytes got %zd\n",
 272                         data_len, resp_data_len);
 273                 rc = -EBADMSG;
 274         } else {
 275                 memcpy(data, resp, len);
 276         }
 277 
 278 free:
 279         /* Convert positive SBEI status */
 280         if (rc > 0) {
 281                 dev_err(occ->dev, "SRAM read returned failure status: %08x\n",
 282                         rc);
 283                 rc = -EBADMSG;
 284         }
 285 
 286         kfree(resp);
 287         return rc;
 288 }
 289 
 290 static int occ_putsram(struct occ *occ, u32 address, const void *data,
 291                        ssize_t len)
 292 {
 293         size_t cmd_len, buf_len, resp_len, resp_data_len;
 294         u32 data_len = ((len + 7) / 8) * 8;     /* must be multiples of 8 B */
 295         __be32 *buf;
 296         int rc;
 297 
 298         /*
 299          * We use the same buffer for command and response, make
 300          * sure it's big enough
 301          */
 302         resp_len = OCC_SBE_STATUS_WORDS;
 303         cmd_len = (data_len >> 2) + 5;
 304         buf_len = max(cmd_len, resp_len);
 305         buf = kzalloc(buf_len << 2, GFP_KERNEL);
 306         if (!buf)
 307                 return -ENOMEM;
 308 
 309         /*
 310          * Magic sequence to do SBE putsram command. SBE will transfer
 311          * data to specified SRAM address.
 312          */
 313         buf[0] = cpu_to_be32(cmd_len);
 314         buf[1] = cpu_to_be32(SBEFIFO_CMD_PUT_OCC_SRAM);
 315         buf[2] = cpu_to_be32(1);
 316         buf[3] = cpu_to_be32(address);
 317         buf[4] = cpu_to_be32(data_len);
 318 
 319         memcpy(&buf[5], data, len);
 320 
 321         rc = sbefifo_submit(occ->sbefifo, buf, cmd_len, buf, &resp_len);
 322         if (rc)
 323                 goto free;
 324 
 325         rc = sbefifo_parse_status(occ->sbefifo, SBEFIFO_CMD_PUT_OCC_SRAM,
 326                                   buf, resp_len, &resp_len);
 327         if (rc)
 328                 goto free;
 329 
 330         if (resp_len != 1) {
 331                 dev_err(occ->dev, "SRAM write response length invalid: %zd\n",
 332                         resp_len);
 333                 rc = -EBADMSG;
 334         } else {
 335                 resp_data_len = be32_to_cpu(buf[0]);
 336                 if (resp_data_len != data_len) {
 337                         dev_err(occ->dev,
 338                                 "SRAM write expected %d bytes got %zd\n",
 339                                 data_len, resp_data_len);
 340                         rc = -EBADMSG;
 341                 }
 342         }
 343 
 344 free:
 345         /* Convert positive SBEI status */
 346         if (rc > 0) {
 347                 dev_err(occ->dev, "SRAM write returned failure status: %08x\n",
 348                         rc);
 349                 rc = -EBADMSG;
 350         }
 351 
 352         kfree(buf);
 353         return rc;
 354 }
 355 
 356 static int occ_trigger_attn(struct occ *occ)
 357 {
 358         __be32 buf[OCC_SBE_STATUS_WORDS];
 359         size_t resp_len, resp_data_len;
 360         int rc;
 361 
 362         BUILD_BUG_ON(OCC_SBE_STATUS_WORDS < 7);
 363         resp_len = OCC_SBE_STATUS_WORDS;
 364 
 365         buf[0] = cpu_to_be32(0x5 + 0x2);        /* Chip-op length in words */
 366         buf[1] = cpu_to_be32(SBEFIFO_CMD_PUT_OCC_SRAM);
 367         buf[2] = cpu_to_be32(0x3);              /* Mode: Circular */
 368         buf[3] = cpu_to_be32(0x0);              /* Address: ignore in mode 3 */
 369         buf[4] = cpu_to_be32(0x8);              /* Data length in bytes */
 370         buf[5] = cpu_to_be32(0x20010000);       /* Trigger OCC attention */
 371         buf[6] = 0;
 372 
 373         rc = sbefifo_submit(occ->sbefifo, buf, 7, buf, &resp_len);
 374         if (rc)
 375                 goto error;
 376 
 377         rc = sbefifo_parse_status(occ->sbefifo, SBEFIFO_CMD_PUT_OCC_SRAM,
 378                                   buf, resp_len, &resp_len);
 379         if (rc)
 380                 goto error;
 381 
 382         if (resp_len != 1) {
 383                 dev_err(occ->dev, "SRAM attn response length invalid: %zd\n",
 384                         resp_len);
 385                 rc = -EBADMSG;
 386         } else {
 387                 resp_data_len = be32_to_cpu(buf[0]);
 388                 if (resp_data_len != 8) {
 389                         dev_err(occ->dev,
 390                                 "SRAM attn expected 8 bytes got %zd\n",
 391                                 resp_data_len);
 392                         rc = -EBADMSG;
 393                 }
 394         }
 395 
 396  error:
 397         /* Convert positive SBEI status */
 398         if (rc > 0) {
 399                 dev_err(occ->dev, "SRAM attn returned failure status: %08x\n",
 400                         rc);
 401                 rc = -EBADMSG;
 402         }
 403 
 404         return rc;
 405 }
 406 
 407 int fsi_occ_submit(struct device *dev, const void *request, size_t req_len,
 408                    void *response, size_t *resp_len)
 409 {
 410         const unsigned long timeout = msecs_to_jiffies(OCC_TIMEOUT_MS);
 411         const unsigned long wait_time =
 412                 msecs_to_jiffies(OCC_CMD_IN_PRG_WAIT_MS);
 413         struct occ *occ = dev_get_drvdata(dev);
 414         struct occ_response *resp = response;
 415         u8 seq_no;
 416         u16 resp_data_length;
 417         unsigned long start;
 418         int rc;
 419 
 420         if (!occ)
 421                 return -ENODEV;
 422 
 423         if (*resp_len < 7) {
 424                 dev_dbg(dev, "Bad resplen %zd\n", *resp_len);
 425                 return -EINVAL;
 426         }
 427 
 428         mutex_lock(&occ->occ_lock);
 429 
 430         /* Extract the seq_no from the command (first byte) */
 431         seq_no = *(const u8 *)request;
 432         rc = occ_putsram(occ, OCC_SRAM_CMD_ADDR, request, req_len);
 433         if (rc)
 434                 goto done;
 435 
 436         rc = occ_trigger_attn(occ);
 437         if (rc)
 438                 goto done;
 439 
 440         /* Read occ response header */
 441         start = jiffies;
 442         do {
 443                 rc = occ_getsram(occ, OCC_SRAM_RSP_ADDR, resp, 8);
 444                 if (rc)
 445                         goto done;
 446 
 447                 if (resp->return_status == OCC_RESP_CMD_IN_PRG ||
 448                     resp->seq_no != seq_no) {
 449                         rc = -ETIMEDOUT;
 450 
 451                         if (time_after(jiffies, start + timeout)) {
 452                                 dev_err(occ->dev, "resp timeout status=%02x "
 453                                         "resp seq_no=%d our seq_no=%d\n",
 454                                         resp->return_status, resp->seq_no,
 455                                         seq_no);
 456                                 goto done;
 457                         }
 458 
 459                         set_current_state(TASK_UNINTERRUPTIBLE);
 460                         schedule_timeout(wait_time);
 461                 }
 462         } while (rc);
 463 
 464         /* Extract size of response data */
 465         resp_data_length = get_unaligned_be16(&resp->data_length);
 466 
 467         /* Message size is data length + 5 bytes header + 2 bytes checksum */
 468         if ((resp_data_length + 7) > *resp_len) {
 469                 rc = -EMSGSIZE;
 470                 goto done;
 471         }
 472 
 473         dev_dbg(dev, "resp_status=%02x resp_data_len=%d\n",
 474                 resp->return_status, resp_data_length);
 475 
 476         /* Grab the rest */
 477         if (resp_data_length > 1) {
 478                 /* already got 3 bytes resp, also need 2 bytes checksum */
 479                 rc = occ_getsram(occ, OCC_SRAM_RSP_ADDR + 8,
 480                                  &resp->data[3], resp_data_length - 1);
 481                 if (rc)
 482                         goto done;
 483         }
 484 
 485         *resp_len = resp_data_length + 7;
 486         rc = occ_verify_checksum(resp, resp_data_length);
 487 
 488  done:
 489         mutex_unlock(&occ->occ_lock);
 490 
 491         return rc;
 492 }
 493 EXPORT_SYMBOL_GPL(fsi_occ_submit);
 494 
 495 static int occ_unregister_child(struct device *dev, void *data)
 496 {
 497         struct platform_device *hwmon_dev = to_platform_device(dev);
 498 
 499         platform_device_unregister(hwmon_dev);
 500 
 501         return 0;
 502 }
 503 
 504 static int occ_probe(struct platform_device *pdev)
 505 {
 506         int rc;
 507         u32 reg;
 508         struct occ *occ;
 509         struct platform_device *hwmon_dev;
 510         struct device *dev = &pdev->dev;
 511         struct platform_device_info hwmon_dev_info = {
 512                 .parent = dev,
 513                 .name = "occ-hwmon",
 514         };
 515 
 516         occ = devm_kzalloc(dev, sizeof(*occ), GFP_KERNEL);
 517         if (!occ)
 518                 return -ENOMEM;
 519 
 520         occ->dev = dev;
 521         occ->sbefifo = dev->parent;
 522         mutex_init(&occ->occ_lock);
 523 
 524         if (dev->of_node) {
 525                 rc = of_property_read_u32(dev->of_node, "reg", &reg);
 526                 if (!rc) {
 527                         /* make sure we don't have a duplicate from dts */
 528                         occ->idx = ida_simple_get(&occ_ida, reg, reg + 1,
 529                                                   GFP_KERNEL);
 530                         if (occ->idx < 0)
 531                                 occ->idx = ida_simple_get(&occ_ida, 1, INT_MAX,
 532                                                           GFP_KERNEL);
 533                 } else {
 534                         occ->idx = ida_simple_get(&occ_ida, 1, INT_MAX,
 535                                                   GFP_KERNEL);
 536                 }
 537         } else {
 538                 occ->idx = ida_simple_get(&occ_ida, 1, INT_MAX, GFP_KERNEL);
 539         }
 540 
 541         platform_set_drvdata(pdev, occ);
 542 
 543         snprintf(occ->name, sizeof(occ->name), "occ%d", occ->idx);
 544         occ->mdev.fops = &occ_fops;
 545         occ->mdev.minor = MISC_DYNAMIC_MINOR;
 546         occ->mdev.name = occ->name;
 547         occ->mdev.parent = dev;
 548 
 549         rc = misc_register(&occ->mdev);
 550         if (rc) {
 551                 dev_err(dev, "failed to register miscdevice: %d\n", rc);
 552                 ida_simple_remove(&occ_ida, occ->idx);
 553                 return rc;
 554         }
 555 
 556         hwmon_dev_info.id = occ->idx;
 557         hwmon_dev = platform_device_register_full(&hwmon_dev_info);
 558         if (!hwmon_dev)
 559                 dev_warn(dev, "failed to create hwmon device\n");
 560 
 561         return 0;
 562 }
 563 
 564 static int occ_remove(struct platform_device *pdev)
 565 {
 566         struct occ *occ = platform_get_drvdata(pdev);
 567 
 568         misc_deregister(&occ->mdev);
 569 
 570         device_for_each_child(&pdev->dev, NULL, occ_unregister_child);
 571 
 572         ida_simple_remove(&occ_ida, occ->idx);
 573 
 574         return 0;
 575 }
 576 
 577 static const struct of_device_id occ_match[] = {
 578         { .compatible = "ibm,p9-occ" },
 579         { },
 580 };
 581 
 582 static struct platform_driver occ_driver = {
 583         .driver = {
 584                 .name = "occ",
 585                 .of_match_table = occ_match,
 586         },
 587         .probe  = occ_probe,
 588         .remove = occ_remove,
 589 };
 590 
 591 static int occ_init(void)
 592 {
 593         return platform_driver_register(&occ_driver);
 594 }
 595 
 596 static void occ_exit(void)
 597 {
 598         platform_driver_unregister(&occ_driver);
 599 
 600         ida_destroy(&occ_ida);
 601 }
 602 
 603 module_init(occ_init);
 604 module_exit(occ_exit);
 605 
 606 MODULE_AUTHOR("Eddie James <eajames@linux.ibm.com>");
 607 MODULE_DESCRIPTION("BMC P9 OCC driver");
 608 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */