root/drivers/fsi/fsi-scom.c

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

DEFINITIONS

This source file includes following definitions.
  1. __put_scom
  2. __get_scom
  3. put_indirect_scom_form0
  4. put_indirect_scom_form1
  5. get_indirect_scom_form0
  6. raw_put_scom
  7. raw_get_scom
  8. handle_fsi2pib_status
  9. handle_pib_status
  10. put_scom
  11. get_scom
  12. scom_read
  13. scom_write
  14. scom_llseek
  15. raw_convert_status
  16. scom_raw_read
  17. scom_raw_write
  18. scom_reset
  19. scom_check
  20. scom_ioctl
  21. scom_open
  22. scom_free
  23. scom_probe
  24. scom_remove
  25. scom_init
  26. scom_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * SCOM FSI Client device driver
   4  *
   5  * Copyright (C) IBM Corporation 2016
   6  */
   7 
   8 #include <linux/fsi.h>
   9 #include <linux/module.h>
  10 #include <linux/cdev.h>
  11 #include <linux/delay.h>
  12 #include <linux/fs.h>
  13 #include <linux/uaccess.h>
  14 #include <linux/slab.h>
  15 #include <linux/list.h>
  16 
  17 #include <uapi/linux/fsi.h>
  18 
  19 #define FSI_ENGID_SCOM          0x5
  20 
  21 /* SCOM engine register set */
  22 #define SCOM_DATA0_REG          0x00
  23 #define SCOM_DATA1_REG          0x04
  24 #define SCOM_CMD_REG            0x08
  25 #define SCOM_FSI2PIB_RESET_REG  0x18
  26 #define SCOM_STATUS_REG         0x1C /* Read */
  27 #define SCOM_PIB_RESET_REG      0x1C /* Write */
  28 
  29 /* Command register */
  30 #define SCOM_WRITE_CMD          0x80000000
  31 #define SCOM_READ_CMD           0x00000000
  32 
  33 /* Status register bits */
  34 #define SCOM_STATUS_ERR_SUMMARY         0x80000000
  35 #define SCOM_STATUS_PROTECTION          0x01000000
  36 #define SCOM_STATUS_PARITY              0x04000000
  37 #define SCOM_STATUS_PIB_ABORT           0x00100000
  38 #define SCOM_STATUS_PIB_RESP_MASK       0x00007000
  39 #define SCOM_STATUS_PIB_RESP_SHIFT      12
  40 
  41 #define SCOM_STATUS_ANY_ERR             (SCOM_STATUS_PROTECTION | \
  42                                          SCOM_STATUS_PARITY |     \
  43                                          SCOM_STATUS_PIB_ABORT | \
  44                                          SCOM_STATUS_PIB_RESP_MASK)
  45 /* SCOM address encodings */
  46 #define XSCOM_ADDR_IND_FLAG             BIT_ULL(63)
  47 #define XSCOM_ADDR_INF_FORM1            BIT_ULL(60)
  48 
  49 /* SCOM indirect stuff */
  50 #define XSCOM_ADDR_DIRECT_PART          0x7fffffffull
  51 #define XSCOM_ADDR_INDIRECT_PART        0x000fffff00000000ull
  52 #define XSCOM_DATA_IND_READ             BIT_ULL(63)
  53 #define XSCOM_DATA_IND_COMPLETE         BIT_ULL(31)
  54 #define XSCOM_DATA_IND_ERR_MASK         0x70000000ull
  55 #define XSCOM_DATA_IND_ERR_SHIFT        28
  56 #define XSCOM_DATA_IND_DATA             0x0000ffffull
  57 #define XSCOM_DATA_IND_FORM1_DATA       0x000fffffffffffffull
  58 #define XSCOM_ADDR_FORM1_LOW            0x000ffffffffull
  59 #define XSCOM_ADDR_FORM1_HI             0xfff00000000ull
  60 #define XSCOM_ADDR_FORM1_HI_SHIFT       20
  61 
  62 /* Retries */
  63 #define SCOM_MAX_RETRIES                100     /* Retries on busy */
  64 #define SCOM_MAX_IND_RETRIES            10      /* Retries indirect not ready */
  65 
  66 struct scom_device {
  67         struct list_head link;
  68         struct fsi_device *fsi_dev;
  69         struct device dev;
  70         struct cdev cdev;
  71         struct mutex lock;
  72         bool dead;
  73 };
  74 
  75 static int __put_scom(struct scom_device *scom_dev, uint64_t value,
  76                       uint32_t addr, uint32_t *status)
  77 {
  78         __be32 data, raw_status;
  79         int rc;
  80 
  81         data = cpu_to_be32((value >> 32) & 0xffffffff);
  82         rc = fsi_device_write(scom_dev->fsi_dev, SCOM_DATA0_REG, &data,
  83                                 sizeof(uint32_t));
  84         if (rc)
  85                 return rc;
  86 
  87         data = cpu_to_be32(value & 0xffffffff);
  88         rc = fsi_device_write(scom_dev->fsi_dev, SCOM_DATA1_REG, &data,
  89                                 sizeof(uint32_t));
  90         if (rc)
  91                 return rc;
  92 
  93         data = cpu_to_be32(SCOM_WRITE_CMD | addr);
  94         rc = fsi_device_write(scom_dev->fsi_dev, SCOM_CMD_REG, &data,
  95                                 sizeof(uint32_t));
  96         if (rc)
  97                 return rc;
  98         rc = fsi_device_read(scom_dev->fsi_dev, SCOM_STATUS_REG, &raw_status,
  99                              sizeof(uint32_t));
 100         if (rc)
 101                 return rc;
 102         *status = be32_to_cpu(raw_status);
 103 
 104         return 0;
 105 }
 106 
 107 static int __get_scom(struct scom_device *scom_dev, uint64_t *value,
 108                       uint32_t addr, uint32_t *status)
 109 {
 110         __be32 data, raw_status;
 111         int rc;
 112 
 113 
 114         *value = 0ULL;
 115         data = cpu_to_be32(SCOM_READ_CMD | addr);
 116         rc = fsi_device_write(scom_dev->fsi_dev, SCOM_CMD_REG, &data,
 117                                 sizeof(uint32_t));
 118         if (rc)
 119                 return rc;
 120         rc = fsi_device_read(scom_dev->fsi_dev, SCOM_STATUS_REG, &raw_status,
 121                              sizeof(uint32_t));
 122         if (rc)
 123                 return rc;
 124 
 125         /*
 126          * Read the data registers even on error, so we don't have
 127          * to interpret the status register here.
 128          */
 129         rc = fsi_device_read(scom_dev->fsi_dev, SCOM_DATA0_REG, &data,
 130                                 sizeof(uint32_t));
 131         if (rc)
 132                 return rc;
 133         *value |= (uint64_t)be32_to_cpu(data) << 32;
 134         rc = fsi_device_read(scom_dev->fsi_dev, SCOM_DATA1_REG, &data,
 135                                 sizeof(uint32_t));
 136         if (rc)
 137                 return rc;
 138         *value |= be32_to_cpu(data);
 139         *status = be32_to_cpu(raw_status);
 140 
 141         return rc;
 142 }
 143 
 144 static int put_indirect_scom_form0(struct scom_device *scom, uint64_t value,
 145                                    uint64_t addr, uint32_t *status)
 146 {
 147         uint64_t ind_data, ind_addr;
 148         int rc, retries, err = 0;
 149 
 150         if (value & ~XSCOM_DATA_IND_DATA)
 151                 return -EINVAL;
 152 
 153         ind_addr = addr & XSCOM_ADDR_DIRECT_PART;
 154         ind_data = (addr & XSCOM_ADDR_INDIRECT_PART) | value;
 155         rc = __put_scom(scom, ind_data, ind_addr, status);
 156         if (rc || (*status & SCOM_STATUS_ANY_ERR))
 157                 return rc;
 158 
 159         for (retries = 0; retries < SCOM_MAX_IND_RETRIES; retries++) {
 160                 rc = __get_scom(scom, &ind_data, addr, status);
 161                 if (rc || (*status & SCOM_STATUS_ANY_ERR))
 162                         return rc;
 163 
 164                 err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT;
 165                 *status = err << SCOM_STATUS_PIB_RESP_SHIFT;
 166                 if ((ind_data & XSCOM_DATA_IND_COMPLETE) || (err != SCOM_PIB_BLOCKED))
 167                         return 0;
 168 
 169                 msleep(1);
 170         }
 171         return rc;
 172 }
 173 
 174 static int put_indirect_scom_form1(struct scom_device *scom, uint64_t value,
 175                                    uint64_t addr, uint32_t *status)
 176 {
 177         uint64_t ind_data, ind_addr;
 178 
 179         if (value & ~XSCOM_DATA_IND_FORM1_DATA)
 180                 return -EINVAL;
 181 
 182         ind_addr = addr & XSCOM_ADDR_FORM1_LOW;
 183         ind_data = value | (addr & XSCOM_ADDR_FORM1_HI) << XSCOM_ADDR_FORM1_HI_SHIFT;
 184         return __put_scom(scom, ind_data, ind_addr, status);
 185 }
 186 
 187 static int get_indirect_scom_form0(struct scom_device *scom, uint64_t *value,
 188                                    uint64_t addr, uint32_t *status)
 189 {
 190         uint64_t ind_data, ind_addr;
 191         int rc, retries, err = 0;
 192 
 193         ind_addr = addr & XSCOM_ADDR_DIRECT_PART;
 194         ind_data = (addr & XSCOM_ADDR_INDIRECT_PART) | XSCOM_DATA_IND_READ;
 195         rc = __put_scom(scom, ind_data, ind_addr, status);
 196         if (rc || (*status & SCOM_STATUS_ANY_ERR))
 197                 return rc;
 198 
 199         for (retries = 0; retries < SCOM_MAX_IND_RETRIES; retries++) {
 200                 rc = __get_scom(scom, &ind_data, addr, status);
 201                 if (rc || (*status & SCOM_STATUS_ANY_ERR))
 202                         return rc;
 203 
 204                 err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT;
 205                 *status = err << SCOM_STATUS_PIB_RESP_SHIFT;
 206                 *value = ind_data & XSCOM_DATA_IND_DATA;
 207 
 208                 if ((ind_data & XSCOM_DATA_IND_COMPLETE) || (err != SCOM_PIB_BLOCKED))
 209                         return 0;
 210 
 211                 msleep(1);
 212         }
 213         return rc;
 214 }
 215 
 216 static int raw_put_scom(struct scom_device *scom, uint64_t value,
 217                         uint64_t addr, uint32_t *status)
 218 {
 219         if (addr & XSCOM_ADDR_IND_FLAG) {
 220                 if (addr & XSCOM_ADDR_INF_FORM1)
 221                         return put_indirect_scom_form1(scom, value, addr, status);
 222                 else
 223                         return put_indirect_scom_form0(scom, value, addr, status);
 224         } else
 225                 return __put_scom(scom, value, addr, status);
 226 }
 227 
 228 static int raw_get_scom(struct scom_device *scom, uint64_t *value,
 229                         uint64_t addr, uint32_t *status)
 230 {
 231         if (addr & XSCOM_ADDR_IND_FLAG) {
 232                 if (addr & XSCOM_ADDR_INF_FORM1)
 233                         return -ENXIO;
 234                 return get_indirect_scom_form0(scom, value, addr, status);
 235         } else
 236                 return __get_scom(scom, value, addr, status);
 237 }
 238 
 239 static int handle_fsi2pib_status(struct scom_device *scom, uint32_t status)
 240 {
 241         uint32_t dummy = -1;
 242 
 243         if (status & SCOM_STATUS_PROTECTION)
 244                 return -EPERM;
 245         if (status & SCOM_STATUS_PARITY) {
 246                 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
 247                                  sizeof(uint32_t));
 248                 return -EIO;
 249         }
 250         /* Return -EBUSY on PIB abort to force a retry */
 251         if (status & SCOM_STATUS_PIB_ABORT)
 252                 return -EBUSY;
 253         return 0;
 254 }
 255 
 256 static int handle_pib_status(struct scom_device *scom, uint8_t status)
 257 {
 258         uint32_t dummy = -1;
 259 
 260         if (status == SCOM_PIB_SUCCESS)
 261                 return 0;
 262         if (status == SCOM_PIB_BLOCKED)
 263                 return -EBUSY;
 264 
 265         /* Reset the bridge */
 266         fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
 267                          sizeof(uint32_t));
 268 
 269         switch(status) {
 270         case SCOM_PIB_OFFLINE:
 271                 return -ENODEV;
 272         case SCOM_PIB_BAD_ADDR:
 273                 return -ENXIO;
 274         case SCOM_PIB_TIMEOUT:
 275                 return -ETIMEDOUT;
 276         case SCOM_PIB_PARTIAL:
 277         case SCOM_PIB_CLK_ERR:
 278         case SCOM_PIB_PARITY_ERR:
 279         default:
 280                 return -EIO;
 281         }
 282 }
 283 
 284 static int put_scom(struct scom_device *scom, uint64_t value,
 285                     uint64_t addr)
 286 {
 287         uint32_t status, dummy = -1;
 288         int rc, retries;
 289 
 290         for (retries = 0; retries < SCOM_MAX_RETRIES; retries++) {
 291                 rc = raw_put_scom(scom, value, addr, &status);
 292                 if (rc) {
 293                         /* Try resetting the bridge if FSI fails */
 294                         if (rc != -ENODEV && retries == 0) {
 295                                 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG,
 296                                                  &dummy, sizeof(uint32_t));
 297                                 rc = -EBUSY;
 298                         } else
 299                                 return rc;
 300                 } else
 301                         rc = handle_fsi2pib_status(scom, status);
 302                 if (rc && rc != -EBUSY)
 303                         break;
 304                 if (rc == 0) {
 305                         rc = handle_pib_status(scom,
 306                                                (status & SCOM_STATUS_PIB_RESP_MASK)
 307                                                >> SCOM_STATUS_PIB_RESP_SHIFT);
 308                         if (rc && rc != -EBUSY)
 309                                 break;
 310                 }
 311                 if (rc == 0)
 312                         break;
 313                 msleep(1);
 314         }
 315         return rc;
 316 }
 317 
 318 static int get_scom(struct scom_device *scom, uint64_t *value,
 319                     uint64_t addr)
 320 {
 321         uint32_t status, dummy = -1;
 322         int rc, retries;
 323 
 324         for (retries = 0; retries < SCOM_MAX_RETRIES; retries++) {
 325                 rc = raw_get_scom(scom, value, addr, &status);
 326                 if (rc) {
 327                         /* Try resetting the bridge if FSI fails */
 328                         if (rc != -ENODEV && retries == 0) {
 329                                 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG,
 330                                                  &dummy, sizeof(uint32_t));
 331                                 rc = -EBUSY;
 332                         } else
 333                                 return rc;
 334                 } else
 335                         rc = handle_fsi2pib_status(scom, status);
 336                 if (rc && rc != -EBUSY)
 337                         break;
 338                 if (rc == 0) {
 339                         rc = handle_pib_status(scom,
 340                                                (status & SCOM_STATUS_PIB_RESP_MASK)
 341                                                >> SCOM_STATUS_PIB_RESP_SHIFT);
 342                         if (rc && rc != -EBUSY)
 343                                 break;
 344                 }
 345                 if (rc == 0)
 346                         break;
 347                 msleep(1);
 348         }
 349         return rc;
 350 }
 351 
 352 static ssize_t scom_read(struct file *filep, char __user *buf, size_t len,
 353                          loff_t *offset)
 354 {
 355         struct scom_device *scom = filep->private_data;
 356         struct device *dev = &scom->fsi_dev->dev;
 357         uint64_t val;
 358         int rc;
 359 
 360         if (len != sizeof(uint64_t))
 361                 return -EINVAL;
 362 
 363         mutex_lock(&scom->lock);
 364         if (scom->dead)
 365                 rc = -ENODEV;
 366         else
 367                 rc = get_scom(scom, &val, *offset);
 368         mutex_unlock(&scom->lock);
 369         if (rc) {
 370                 dev_dbg(dev, "get_scom fail:%d\n", rc);
 371                 return rc;
 372         }
 373 
 374         rc = copy_to_user(buf, &val, len);
 375         if (rc)
 376                 dev_dbg(dev, "copy to user failed:%d\n", rc);
 377 
 378         return rc ? rc : len;
 379 }
 380 
 381 static ssize_t scom_write(struct file *filep, const char __user *buf,
 382                           size_t len, loff_t *offset)
 383 {
 384         int rc;
 385         struct scom_device *scom = filep->private_data;
 386         struct device *dev = &scom->fsi_dev->dev;
 387         uint64_t val;
 388 
 389         if (len != sizeof(uint64_t))
 390                 return -EINVAL;
 391 
 392         rc = copy_from_user(&val, buf, len);
 393         if (rc) {
 394                 dev_dbg(dev, "copy from user failed:%d\n", rc);
 395                 return -EINVAL;
 396         }
 397 
 398         mutex_lock(&scom->lock);
 399         if (scom->dead)
 400                 rc = -ENODEV;
 401         else
 402                 rc = put_scom(scom, val, *offset);
 403         mutex_unlock(&scom->lock);
 404         if (rc) {
 405                 dev_dbg(dev, "put_scom failed with:%d\n", rc);
 406                 return rc;
 407         }
 408 
 409         return len;
 410 }
 411 
 412 static loff_t scom_llseek(struct file *file, loff_t offset, int whence)
 413 {
 414         switch (whence) {
 415         case SEEK_CUR:
 416                 break;
 417         case SEEK_SET:
 418                 file->f_pos = offset;
 419                 break;
 420         default:
 421                 return -EINVAL;
 422         }
 423 
 424         return offset;
 425 }
 426 
 427 static void raw_convert_status(struct scom_access *acc, uint32_t status)
 428 {
 429         acc->pib_status = (status & SCOM_STATUS_PIB_RESP_MASK) >>
 430                 SCOM_STATUS_PIB_RESP_SHIFT;
 431         acc->intf_errors = 0;
 432 
 433         if (status & SCOM_STATUS_PROTECTION)
 434                 acc->intf_errors |= SCOM_INTF_ERR_PROTECTION;
 435         else if (status & SCOM_STATUS_PARITY)
 436                 acc->intf_errors |= SCOM_INTF_ERR_PARITY;
 437         else if (status & SCOM_STATUS_PIB_ABORT)
 438                 acc->intf_errors |= SCOM_INTF_ERR_ABORT;
 439         else if (status & SCOM_STATUS_ERR_SUMMARY)
 440                 acc->intf_errors |= SCOM_INTF_ERR_UNKNOWN;
 441 }
 442 
 443 static int scom_raw_read(struct scom_device *scom, void __user *argp)
 444 {
 445         struct scom_access acc;
 446         uint32_t status;
 447         int rc;
 448 
 449         if (copy_from_user(&acc, argp, sizeof(struct scom_access)))
 450                 return -EFAULT;
 451 
 452         rc = raw_get_scom(scom, &acc.data, acc.addr, &status);
 453         if (rc)
 454                 return rc;
 455         raw_convert_status(&acc, status);
 456         if (copy_to_user(argp, &acc, sizeof(struct scom_access)))
 457                 return -EFAULT;
 458         return 0;
 459 }
 460 
 461 static int scom_raw_write(struct scom_device *scom, void __user *argp)
 462 {
 463         u64 prev_data, mask, data;
 464         struct scom_access acc;
 465         uint32_t status;
 466         int rc;
 467 
 468         if (copy_from_user(&acc, argp, sizeof(struct scom_access)))
 469                 return -EFAULT;
 470 
 471         if (acc.mask) {
 472                 rc = raw_get_scom(scom, &prev_data, acc.addr, &status);
 473                 if (rc)
 474                         return rc;
 475                 if (status & SCOM_STATUS_ANY_ERR)
 476                         goto fail;
 477                 mask = acc.mask;
 478         } else {
 479                 prev_data = mask = -1ull;
 480         }
 481         data = (prev_data & ~mask) | (acc.data & mask);
 482         rc = raw_put_scom(scom, data, acc.addr, &status);
 483         if (rc)
 484                 return rc;
 485  fail:
 486         raw_convert_status(&acc, status);
 487         if (copy_to_user(argp, &acc, sizeof(struct scom_access)))
 488                 return -EFAULT;
 489         return 0;
 490 }
 491 
 492 static int scom_reset(struct scom_device *scom, void __user *argp)
 493 {
 494         uint32_t flags, dummy = -1;
 495         int rc = 0;
 496 
 497         if (get_user(flags, (__u32 __user *)argp))
 498                 return -EFAULT;
 499         if (flags & SCOM_RESET_PIB)
 500                 rc = fsi_device_write(scom->fsi_dev, SCOM_PIB_RESET_REG, &dummy,
 501                                       sizeof(uint32_t));
 502         if (!rc && (flags & (SCOM_RESET_PIB | SCOM_RESET_INTF)))
 503                 rc = fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
 504                                       sizeof(uint32_t));
 505         return rc;
 506 }
 507 
 508 static int scom_check(struct scom_device *scom, void __user *argp)
 509 {
 510         /* Still need to find out how to get "protected" */
 511         return put_user(SCOM_CHECK_SUPPORTED, (__u32 __user *)argp);
 512 }
 513 
 514 static long scom_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 515 {
 516         struct scom_device *scom = file->private_data;
 517         void __user *argp = (void __user *)arg;
 518         int rc = -ENOTTY;
 519 
 520         mutex_lock(&scom->lock);
 521         if (scom->dead) {
 522                 mutex_unlock(&scom->lock);
 523                 return -ENODEV;
 524         }
 525         switch(cmd) {
 526         case FSI_SCOM_CHECK:
 527                 rc = scom_check(scom, argp);
 528                 break;
 529         case FSI_SCOM_READ:
 530                 rc = scom_raw_read(scom, argp);
 531                 break;
 532         case FSI_SCOM_WRITE:
 533                 rc = scom_raw_write(scom, argp);
 534                 break;
 535         case FSI_SCOM_RESET:
 536                 rc = scom_reset(scom, argp);
 537                 break;
 538         }
 539         mutex_unlock(&scom->lock);
 540         return rc;
 541 }
 542 
 543 static int scom_open(struct inode *inode, struct file *file)
 544 {
 545         struct scom_device *scom = container_of(inode->i_cdev, struct scom_device, cdev);
 546 
 547         file->private_data = scom;
 548 
 549         return 0;
 550 }
 551 
 552 static const struct file_operations scom_fops = {
 553         .owner          = THIS_MODULE,
 554         .open           = scom_open,
 555         .llseek         = scom_llseek,
 556         .read           = scom_read,
 557         .write          = scom_write,
 558         .unlocked_ioctl = scom_ioctl,
 559 };
 560 
 561 static void scom_free(struct device *dev)
 562 {
 563         struct scom_device *scom = container_of(dev, struct scom_device, dev);
 564 
 565         put_device(&scom->fsi_dev->dev);
 566         kfree(scom);
 567 }
 568 
 569 static int scom_probe(struct device *dev)
 570 {
 571         struct fsi_device *fsi_dev = to_fsi_dev(dev);
 572         struct scom_device *scom;
 573         int rc, didx;
 574 
 575         scom = kzalloc(sizeof(*scom), GFP_KERNEL);
 576         if (!scom)
 577                 return -ENOMEM;
 578         dev_set_drvdata(dev, scom);
 579         mutex_init(&scom->lock);
 580 
 581         /* Grab a reference to the device (parent of our cdev), we'll drop it later */
 582         if (!get_device(dev)) {
 583                 kfree(scom);
 584                 return -ENODEV;
 585         }
 586         scom->fsi_dev = fsi_dev;
 587 
 588         /* Create chardev for userspace access */
 589         scom->dev.type = &fsi_cdev_type;
 590         scom->dev.parent = dev;
 591         scom->dev.release = scom_free;
 592         device_initialize(&scom->dev);
 593 
 594         /* Allocate a minor in the FSI space */
 595         rc = fsi_get_new_minor(fsi_dev, fsi_dev_scom, &scom->dev.devt, &didx);
 596         if (rc)
 597                 goto err;
 598 
 599         dev_set_name(&scom->dev, "scom%d", didx);
 600         cdev_init(&scom->cdev, &scom_fops);
 601         rc = cdev_device_add(&scom->cdev, &scom->dev);
 602         if (rc) {
 603                 dev_err(dev, "Error %d creating char device %s\n",
 604                         rc, dev_name(&scom->dev));
 605                 goto err_free_minor;
 606         }
 607 
 608         return 0;
 609  err_free_minor:
 610         fsi_free_minor(scom->dev.devt);
 611  err:
 612         put_device(&scom->dev);
 613         return rc;
 614 }
 615 
 616 static int scom_remove(struct device *dev)
 617 {
 618         struct scom_device *scom = dev_get_drvdata(dev);
 619 
 620         mutex_lock(&scom->lock);
 621         scom->dead = true;
 622         mutex_unlock(&scom->lock);
 623         cdev_device_del(&scom->cdev, &scom->dev);
 624         fsi_free_minor(scom->dev.devt);
 625         put_device(&scom->dev);
 626 
 627         return 0;
 628 }
 629 
 630 static struct fsi_device_id scom_ids[] = {
 631         {
 632                 .engine_type = FSI_ENGID_SCOM,
 633                 .version = FSI_VERSION_ANY,
 634         },
 635         { 0 }
 636 };
 637 
 638 static struct fsi_driver scom_drv = {
 639         .id_table = scom_ids,
 640         .drv = {
 641                 .name = "scom",
 642                 .bus = &fsi_bus_type,
 643                 .probe = scom_probe,
 644                 .remove = scom_remove,
 645         }
 646 };
 647 
 648 static int scom_init(void)
 649 {
 650         return fsi_driver_register(&scom_drv);
 651 }
 652 
 653 static void scom_exit(void)
 654 {
 655         fsi_driver_unregister(&scom_drv);
 656 }
 657 
 658 module_init(scom_init);
 659 module_exit(scom_exit);
 660 MODULE_LICENSE("GPL");

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