On Thu, Sep 19, 2024 at 11:29:11PM +0530, Shyam Sundar S K wrote: > Add support for handling ASF slave process events as described in the AMD > ASF databook. This involves implementing the correct programming sequence > to manage each ASF packet appropriately. ... > +static void amd_asf_process_target(struct work_struct *work) > +{ > + struct amd_asf_dev *dev = container_of(work, struct amd_asf_dev, work_buf.work); > + unsigned short piix4_smba = dev->port_addr->start; > + u8 data[ASF_BLOCK_MAX_BYTES]; > + u8 bank, reg, cmd; > + u8 len, idx, val; > + > + /* Read target status register */ > + reg = inb_p(ASFSLVSTA); > + > + /* Check if no error bits are set in target status register */ > + if (reg & ASF_ERROR_STATUS) { > + /* Set bank as full */ > + cmd = 0; > + reg = reg | GENMASK(3, 2); reg |= ... > + outb_p(reg, ASFDATABNKSEL); > + } else { > + /* Read data bank */ > + reg = inb_p(ASFDATABNKSEL); > + bank = (reg & BIT(3)) ? 1 : 0; > + /* Set read data bank */ > + if (bank) { > + reg = reg | BIT(4); > + reg = reg & ~BIT(3); > + } else { > + reg = reg & ~BIT(4); > + reg = reg & ~BIT(2); > + } /* Set read data bank */ if (bank) { reg |= BIT(4); reg &= ~BIT(3); } else { reg &= ~BIT(4); reg &= ~BIT(2); } > + /* Read command register */ > + outb_p(reg, ASFDATABNKSEL); > + cmd = inb_p(ASFINDEX); > + len = inb_p(ASFDATARWPTR); > + for (idx = 0; idx < len; idx++) > + data[idx] = inb_p(ASFINDEX); > + /* Clear data bank status */ > + if (bank) { > + reg = reg | BIT(3); > + outb_p(reg, ASFDATABNKSEL); > + } else { > + reg = reg | BIT(2); > + outb_p(reg, ASFDATABNKSEL); > + } /* Clear data bank status */ if (bank) { reg |= BIT(3); outb_p(reg, ASFDATABNKSEL); } else { reg |= BIT(2); outb_p(reg, ASFDATABNKSEL); } > + } > + > + outb_p(0, ASFSETDATARDPTR); > + if (cmd & BIT(0)) > + return; > + > + /* > + * Although i2c_slave_event() returns an appropriate error code, we > + * don't check it here because we're operating in the workqueue context. > + */ > + i2c_slave_event(dev->target, I2C_SLAVE_WRITE_REQUESTED, &val); > + for (idx = 0; idx < len; idx++) { > + val = data[idx]; > + i2c_slave_event(dev->target, I2C_SLAVE_WRITE_RECEIVED, &val); > + } > + i2c_slave_event(dev->target, I2C_SLAVE_STOP, &val); > +} ... Perhaps it's time to have struct device *dev = &pdev->dev; > + ret = devm_delayed_work_autocancel(&pdev->dev, &asf_dev->work_buf, amd_asf_process_target); > + if (ret) > + return dev_err_probe(&pdev->dev, ret, "failed to create work queue\n"); ...and this, in particular, becomes shorter. ret = devm_delayed_work_autocancel(dev, &asf_dev->work_buf, amd_asf_process_target); if (ret) return dev_err_probe(dev, ret, "failed to create work queue\n"); > + irq = platform_get_irq(pdev, 0); > + if (irq < 0) > + return dev_err_probe(&pdev->dev, irq, "missing IRQ resources\n"); > + > + ret = devm_request_irq(&pdev->dev, irq, amd_asf_irq_handler, IRQF_SHARED, > + "amd_asf", asf_dev); This even can be one line after proposed change. > + if (ret) > + return dev_err_probe(&pdev->dev, ret, "Unable to request irq: %d for use\n", irq); ... With the above changes being applied Reviewed-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx> -- With Best Regards, Andy Shevchenko