]> Git Repo - J-linux.git/commitdiff
Merge tag 'i3c/for-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux
authorLinus Torvalds <[email protected]>
Sun, 5 Nov 2023 02:25:36 +0000 (16:25 -1000)
committerLinus Torvalds <[email protected]>
Sun, 5 Nov 2023 02:25:36 +0000 (16:25 -1000)
Pull i3c updates from Alexandre Belloni:
 "There are now more fixes because as stated in my previous pull
  request, people now have access to actual hardware.

  Core:

   - handle IBI in the proper order

  Drivers:

   - cdns: fix status register access

   - mipi-i3c-hci: many fixes now that the driver has been actually
     tested

   - svc: many IBI fixes, correct compatible string, fix hot join corner
     cases"

* tag 'i3c/for-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux: (29 commits)
  i3c: master: handle IBIs in order they came
  i3c: master: mipi-i3c-hci: Fix a kernel panic for accessing DAT_data.
  i3c: master: svc: fix compatibility string mismatch with binding doc
  i3c: master: svc: fix random hot join failure since timeout error
  i3c: master: svc: fix SDA keep low when polling IBIWON timeout happen
  i3c: master: svc: fix check wrong status register in irq handler
  i3c: master: svc: fix ibi may not return mandatory data byte
  i3c: master: svc: fix wrong data return when IBI happen during start frame
  i3c: master: svc: fix race condition in ibi work thread
  i3c: Fix typo "Provisional ID" to "Provisioned ID"
  i3c: Fix potential refcount leak in i3c_master_register_new_i3c_devs
  i3c: mipi-i3c-hci: Resume controller after aborted transfer
  i3c: mipi-i3c-hci: Resume controller explicitly
  i3c: mipi-i3c-hci: Fix missing xfer->completion in hci_cmd_v1_daa()
  i3c: mipi-i3c-hci: Do not unmap region not mapped for transfer
  i3c: mipi-i3c-hci: Set number of SW enabled Ring Bundles earlier
  i3c: mipi-i3c-hci: Fix race between bus cleanup and interrupt
  i3c: mipi-i3c-hci: Set ring start request together with enable
  i3c: mipi-i3c-hci: Remove BUG() when Ring Abort request times out
  i3c: mipi-i3c-hci: Fix out of bounds access in hci_dma_irq_handler
  ...

1  2 
Documentation/devicetree/bindings/i3c/i3c.yaml
drivers/i3c/master.c
include/linux/i3c/master.h

index d9483fbd24543925b0d1eeec4809bbc6de94fc7b,f8ac7a3e312364fa8b60097cc1d1b26465eb69c3..c816e295d5651f372c4884751c9954a953d8838a
@@@ -55,12 -55,6 +55,12 @@@ properties
  
        May not be supported by all controllers.
  
 +  mctp-controller:
 +    type: boolean
 +    description: |
 +      Indicates that the system is accessible via this bus as an endpoint for
 +      MCTP over I3C transport.
 +
  required:
    - "#address-cells"
    - "#size-cells"
@@@ -125,12 -119,12 +125,12 @@@ patternProperties
                  minimum: 0
                  maximum: 0x7f
                - description: |
-                   First half of the Provisional ID (following the PID
+                   First half of the Provisioned ID (following the PID
                    definition provided by the I3C specification).
  
                    Contains the manufacturer ID left-shifted by 1.
                - description: |
-                   Second half of the Provisional ID (following the PID
+                   Second half of the Provisioned ID (following the PID
                    definition provided by the I3C specification).
  
                    Contains the ORing of the part ID left-shifted by 16,
diff --combined drivers/i3c/master.c
index 959ec5269376fb42d78a8faecef8ffa0aa37104b,0cdc94e4cb7778190e7411398648d9131caa5ef3..95caa162706f5543a91fb40cffaa2927b25b64c7
@@@ -22,7 -22,6 +22,7 @@@
  static DEFINE_IDR(i3c_bus_idr);
  static DEFINE_MUTEX(i3c_core_lock);
  static int __i3c_first_dynamic_bus_num;
 +static BLOCKING_NOTIFIER_HEAD(i3c_bus_notifier);
  
  /**
   * i3c_bus_maintenance_lock - Lock the bus for a maintenance operation
@@@ -454,36 -453,6 +454,36 @@@ static int i3c_bus_init(struct i3c_bus 
        return 0;
  }
  
 +void i3c_for_each_bus_locked(int (*fn)(struct i3c_bus *bus, void *data),
 +                           void *data)
 +{
 +      struct i3c_bus *bus;
 +      int id;
 +
 +      mutex_lock(&i3c_core_lock);
 +      idr_for_each_entry(&i3c_bus_idr, bus, id)
 +              fn(bus, data);
 +      mutex_unlock(&i3c_core_lock);
 +}
 +EXPORT_SYMBOL_GPL(i3c_for_each_bus_locked);
 +
 +int i3c_register_notifier(struct notifier_block *nb)
 +{
 +      return blocking_notifier_chain_register(&i3c_bus_notifier, nb);
 +}
 +EXPORT_SYMBOL_GPL(i3c_register_notifier);
 +
 +int i3c_unregister_notifier(struct notifier_block *nb)
 +{
 +      return blocking_notifier_chain_unregister(&i3c_bus_notifier, nb);
 +}
 +EXPORT_SYMBOL_GPL(i3c_unregister_notifier);
 +
 +static void i3c_bus_notify(struct i3c_bus *bus, unsigned int action)
 +{
 +      blocking_notifier_call_chain(&i3c_bus_notifier, action, bus);
 +}
 +
  static const char * const i3c_bus_mode_strings[] = {
        [I3C_BUS_MODE_PURE] = "pure",
        [I3C_BUS_MODE_MIXED_FAST] = "mixed-fast",
@@@ -1556,9 -1525,11 +1556,11 @@@ i3c_master_register_new_i3c_devs(struc
                        desc->dev->dev.of_node = desc->boardinfo->of_node;
  
                ret = device_register(&desc->dev->dev);
-               if (ret)
+               if (ret) {
                        dev_err(&master->dev,
                                "Failed to add I3C device (err = %d)\n", ret);
+                       put_device(&desc->dev->dev);
+               }
        }
  }
  
@@@ -2340,7 -2311,7 +2342,7 @@@ static int i3c_master_i2c_adapter_init(
        adap->dev.parent = master->dev.parent;
        adap->owner = master->dev.parent->driver->owner;
        adap->algo = &i3c_master_i2c_algo;
-       strncpy(adap->name, dev_name(master->dev.parent), sizeof(adap->name));
+       strscpy(adap->name, dev_name(master->dev.parent), sizeof(adap->name));
  
        /* FIXME: Should we allow i3c masters to override these values? */
        adap->timeout = 1000;
@@@ -2403,7 -2374,7 +2405,7 @@@ static void i3c_master_unregister_i3c_d
  void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot)
  {
        atomic_inc(&dev->ibi->pending_ibis);
-       queue_work(dev->common.master->wq, &slot->work);
+       queue_work(dev->ibi->wq, &slot->work);
  }
  EXPORT_SYMBOL_GPL(i3c_master_queue_ibi);
  
@@@ -2660,6 -2631,10 +2662,10 @@@ int i3c_master_register(struct i3c_mast
        device_initialize(&master->dev);
        dev_set_name(&master->dev, "i3c-%d", i3cbus->id);
  
+       master->dev.dma_mask = parent->dma_mask;
+       master->dev.coherent_dma_mask = parent->coherent_dma_mask;
+       master->dev.dma_parms = parent->dma_parms;
        ret = of_populate_i3c_bus(master);
        if (ret)
                goto err_put_dev;
        if (ret)
                goto err_del_dev;
  
 +      i3c_bus_notify(i3cbus, I3C_NOTIFY_BUS_ADD);
 +
        /*
         * We're done initializing the bus and the controller, we can now
         * register I3C devices discovered during the initial DAA.
@@@ -2747,8 -2720,6 +2753,8 @@@ EXPORT_SYMBOL_GPL(i3c_master_register)
   */
  void i3c_master_unregister(struct i3c_master_controller *master)
  {
 +      i3c_bus_notify(&master->bus, I3C_NOTIFY_BUS_REMOVE);
 +
        i3c_master_i2c_adapter_cleanup(master);
        i3c_master_unregister_i3c_devs(master);
        i3c_master_bus_cleanup(master);
@@@ -2848,6 -2819,12 +2854,12 @@@ int i3c_dev_request_ibi_locked(struct i
        if (!ibi)
                return -ENOMEM;
  
+       ibi->wq = alloc_ordered_workqueue(dev_name(i3cdev_to_dev(dev->dev)), WQ_MEM_RECLAIM);
+       if (!ibi->wq) {
+               kfree(ibi);
+               return -ENOMEM;
+       }
        atomic_set(&ibi->pending_ibis, 0);
        init_completion(&ibi->all_ibis_handled);
        ibi->handler = req->handler;
@@@ -2875,6 -2852,12 +2887,12 @@@ void i3c_dev_free_ibi_locked(struct i3c
                WARN_ON(i3c_dev_disable_ibi_locked(dev));
  
        master->ops->free_ibi(dev);
+       if (dev->ibi->wq) {
+               destroy_workqueue(dev->ibi->wq);
+               dev->ibi->wq = NULL;
+       }
        kfree(dev->ibi);
        dev->ibi = NULL;
  }
index db909ef79be47dbbbd19fac1e6d4ff20de8ed1c0,349d7d0dda7308abff387287b5d9da2ea07caa15..24c1863b86e2b6940d263555515039fa0b317203
  
  struct i2c_client;
  
 +/* notifier actions. notifier call data is the struct i3c_bus */
 +enum {
 +      I3C_NOTIFY_BUS_ADD,
 +      I3C_NOTIFY_BUS_REMOVE,
 +};
 +
  struct i3c_master_controller;
  struct i3c_bus;
  struct i3c_device;
@@@ -135,6 -129,7 +135,7 @@@ struct i3c_ibi_slot 
   *                 rejected by the master
   * @num_slots: number of IBI slots reserved for this device
   * @enabled: reflect the IBI status
+  * @wq: workqueue used to execute IBI handlers.
   * @handler: IBI handler specified at i3c_device_request_ibi() call time. This
   *         handler will be called from the controller workqueue, and as such
   *         is allowed to sleep (though it is recommended to process the IBI
@@@ -157,6 -152,7 +158,7 @@@ struct i3c_device_ibi_info 
        unsigned int max_payload_len;
        unsigned int num_slots;
        unsigned int enabled;
+       struct workqueue_struct *wq;
        void (*handler)(struct i3c_device *dev,
                        const struct i3c_ibi_payload *payload);
  };
   *             assigned a dynamic address by the master. Will be used during
   *             bus initialization to assign it a specific dynamic address
   *             before starting DAA (Dynamic Address Assignment)
-  * @pid: I3C Provisional ID exposed by the device. This is a unique identifier
+  * @pid: I3C Provisioned ID exposed by the device. This is a unique identifier
   *     that may be used to attach boardinfo to i3c_dev_desc when the device
   *     does not have a static address
   * @of_node: optional DT node in case the device has been described in the DT
@@@ -475,7 -471,7 +477,7 @@@ struct i3c_master_controller_ops 
   * @boardinfo.i2c: list of I2C boardinfo objects
   * @boardinfo: board-level information attached to devices connected on the bus
   * @bus: I3C bus exposed by this master
-  * @wq: workqueue used to execute IBI handlers. Can also be used by master
+  * @wq: workqueue which can be used by master
   *    drivers if they need to postpone operations that need to take place
   *    in a thread context. Typical examples are Hot Join processing which
   *    requires taking the bus lock in maintenance, which in turn, can only
@@@ -658,9 -654,4 +660,9 @@@ void i3c_master_queue_ibi(struct i3c_de
  
  struct i3c_ibi_slot *i3c_master_get_free_ibi_slot(struct i3c_dev_desc *dev);
  
 +void i3c_for_each_bus_locked(int (*fn)(struct i3c_bus *bus, void *data),
 +                           void *data);
 +int i3c_register_notifier(struct notifier_block *nb);
 +int i3c_unregister_notifier(struct notifier_block *nb);
 +
  #endif /* I3C_MASTER_H */
This page took 0.076162 seconds and 4 git commands to generate.