Merge tag 'mailbox-v5.10' of git://git.linaro.org/landing-teams/working/fujitsu/integration

Pull mailbox updates from Jassi Brar:

- arm: implementation of mhu as a doorbell driver and conversion of
dt-bindings to json-schema

- mediatek: fix platform_get_irq error handling

- bcm: convert tasklets to use new tasklet_setup api

- core: fix race cause by hrtimer starting inappropriately

* tag 'mailbox-v5.10' of git://git.linaro.org/landing-teams/working/fujitsu/integration:
mailbox: avoid timer start from callback
maiblox: mediatek: Fix handling of platform_get_irq() error
mailbox: arm_mhu: Add ARM MHU doorbell driver
mailbox: arm_mhu: Match only if compatible is "arm,mhu"
dt-bindings: mailbox: add doorbell support to ARM MHU
dt-bindings: mailbox : arm,mhu: Convert to Json-schema
mailbox: bcm: convert tasklets to use new tasklet_setup() API

+506 -57
+135
Documentation/devicetree/bindings/mailbox/arm,mhu.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/mailbox/arm,mhu.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: ARM MHU Mailbox Controller 8 + 9 + maintainers: 10 + - Jassi Brar <jaswinder.singh@linaro.org> 11 + 12 + description: | 13 + The ARM's Message-Handling-Unit (MHU) is a mailbox controller that has 3 14 + independent channels/links to communicate with remote processor(s). MHU links 15 + are hardwired on a platform. A link raises interrupt for any received data. 16 + However, there is no specified way of knowing if the sent data has been read 17 + by the remote. This driver assumes the sender polls STAT register and the 18 + remote clears it after having read the data. The last channel is specified to 19 + be a 'Secure' resource, hence can't be used by Linux running NS. 20 + 21 + The MHU hardware also allows operations in doorbell mode. The MHU drives the 22 + interrupt signal using a 32-bit register, with all 32-bits logically ORed 23 + together. It provides a set of registers to enable software to set, clear and 24 + check the status of each of the bits of this register independently. The use 25 + of 32 bits per interrupt line enables software to provide more information 26 + about the source of the interrupt. For example, each bit of the register can 27 + be associated with a type of event that can contribute to raising the 28 + interrupt. Each of the 32-bits can be used as "doorbell" to alert the remote 29 + processor. 30 + 31 + # We need a select here so we don't match all nodes with 'arm,primecell' 32 + select: 33 + properties: 34 + compatible: 35 + contains: 36 + enum: 37 + - arm,mhu 38 + - arm,mhu-doorbell 39 + required: 40 + - compatible 41 + 42 + properties: 43 + compatible: 44 + oneOf: 45 + - description: Data transfer mode 46 + items: 47 + - const: arm,mhu 48 + - const: arm,primecell 49 + 50 + - description: Doorbell mode 51 + items: 52 + - const: arm,mhu-doorbell 53 + - const: arm,primecell 54 + 55 + 56 + reg: 57 + maxItems: 1 58 + 59 + interrupts: 60 + items: 61 + - description: low-priority non-secure 62 + - description: high-priority non-secure 63 + - description: Secure 64 + maxItems: 3 65 + 66 + clocks: 67 + maxItems: 1 68 + 69 + clock-names: 70 + items: 71 + - const: apb_pclk 72 + 73 + '#mbox-cells': 74 + description: | 75 + Set to 1 in data transfer mode and represents index of the channel. 76 + Set to 2 in doorbell mode and represents index of the channel and doorbell 77 + number. 78 + enum: [ 1, 2 ] 79 + 80 + required: 81 + - compatible 82 + - reg 83 + - interrupts 84 + - '#mbox-cells' 85 + 86 + additionalProperties: false 87 + 88 + examples: 89 + # Data transfer mode. 90 + - | 91 + soc { 92 + #address-cells = <2>; 93 + #size-cells = <2>; 94 + 95 + mhuA: mailbox@2b1f0000 { 96 + #mbox-cells = <1>; 97 + compatible = "arm,mhu", "arm,primecell"; 98 + reg = <0 0x2b1f0000 0 0x1000>; 99 + interrupts = <0 36 4>, /* LP-NonSecure */ 100 + <0 35 4>, /* HP-NonSecure */ 101 + <0 37 4>; /* Secure */ 102 + clocks = <&clock 0 2 1>; 103 + clock-names = "apb_pclk"; 104 + }; 105 + 106 + mhu_client_scb: scb@2e000000 { 107 + compatible = "fujitsu,mb86s70-scb-1.0"; 108 + reg = <0 0x2e000000 0 0x4000>; 109 + mboxes = <&mhuA 1>; /* HP-NonSecure */ 110 + }; 111 + }; 112 + 113 + # Doorbell mode. 114 + - | 115 + soc { 116 + #address-cells = <2>; 117 + #size-cells = <2>; 118 + 119 + mhuB: mailbox@2b2f0000 { 120 + #mbox-cells = <2>; 121 + compatible = "arm,mhu-doorbell", "arm,primecell"; 122 + reg = <0 0x2b2f0000 0 0x1000>; 123 + interrupts = <0 36 4>, /* LP-NonSecure */ 124 + <0 35 4>, /* HP-NonSecure */ 125 + <0 37 4>; /* Secure */ 126 + clocks = <&clock 0 2 1>; 127 + clock-names = "apb_pclk"; 128 + }; 129 + 130 + mhu_client_scpi: scpi@2f000000 { 131 + compatible = "arm,scpi"; 132 + reg = <0 0x2f000000 0 0x200>; 133 + mboxes = <&mhuB 1 4>; /* HP-NonSecure, 5th doorbell */ 134 + }; 135 + };
-43
Documentation/devicetree/bindings/mailbox/arm-mhu.txt
··· 1 - ARM MHU Mailbox Driver 2 - ====================== 3 - 4 - The ARM's Message-Handling-Unit (MHU) is a mailbox controller that has 5 - 3 independent channels/links to communicate with remote processor(s). 6 - MHU links are hardwired on a platform. A link raises interrupt for any 7 - received data. However, there is no specified way of knowing if the sent 8 - data has been read by the remote. This driver assumes the sender polls 9 - STAT register and the remote clears it after having read the data. 10 - The last channel is specified to be a 'Secure' resource, hence can't be 11 - used by Linux running NS. 12 - 13 - Mailbox Device Node: 14 - ==================== 15 - 16 - Required properties: 17 - -------------------- 18 - - compatible: Shall be "arm,mhu" & "arm,primecell" 19 - - reg: Contains the mailbox register address range (base 20 - address and length) 21 - - #mbox-cells Shall be 1 - the index of the channel needed. 22 - - interrupts: Contains the interrupt information corresponding to 23 - each of the 3 links of MHU. 24 - 25 - Example: 26 - -------- 27 - 28 - mhu: mailbox@2b1f0000 { 29 - #mbox-cells = <1>; 30 - compatible = "arm,mhu", "arm,primecell"; 31 - reg = <0 0x2b1f0000 0x1000>; 32 - interrupts = <0 36 4>, /* LP-NonSecure */ 33 - <0 35 4>, /* HP-NonSecure */ 34 - <0 37 4>; /* Secure */ 35 - clocks = <&clock 0 2 1>; 36 - clock-names = "apb_pclk"; 37 - }; 38 - 39 - mhu_client: scb@2e000000 { 40 - compatible = "fujitsu,mb86s70-scb-1.0"; 41 - reg = <0 0x2e000000 0x4000>; 42 - mboxes = <&mhu 1>; /* HP-NonSecure */ 43 - };
+1 -1
drivers/mailbox/Makefile
··· 5 5 6 6 obj-$(CONFIG_MAILBOX_TEST) += mailbox-test.o 7 7 8 - obj-$(CONFIG_ARM_MHU) += arm_mhu.o 8 + obj-$(CONFIG_ARM_MHU) += arm_mhu.o arm_mhu_db.o 9 9 10 10 obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o 11 11
+3
drivers/mailbox/arm_mhu.c
··· 113 113 struct device *dev = &adev->dev; 114 114 int mhu_reg[MHU_CHANS] = {MHU_LP_OFFSET, MHU_HP_OFFSET, MHU_SEC_OFFSET}; 115 115 116 + if (!of_device_is_compatible(dev->of_node, "arm,mhu")) 117 + return -ENODEV; 118 + 116 119 /* Allocate memory for device */ 117 120 mhu = devm_kzalloc(dev, sizeof(*mhu), GFP_KERNEL); 118 121 if (!mhu)
+354
drivers/mailbox/arm_mhu_db.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2013-2015 Fujitsu Semiconductor Ltd. 4 + * Copyright (C) 2015 Linaro Ltd. 5 + * Based on ARM MHU driver by Jassi Brar <jaswinder.singh@linaro.org> 6 + * Copyright (C) 2020 ARM Ltd. 7 + */ 8 + 9 + #include <linux/amba/bus.h> 10 + #include <linux/device.h> 11 + #include <linux/err.h> 12 + #include <linux/interrupt.h> 13 + #include <linux/io.h> 14 + #include <linux/kernel.h> 15 + #include <linux/mailbox_controller.h> 16 + #include <linux/module.h> 17 + #include <linux/of.h> 18 + #include <linux/of_device.h> 19 + 20 + #define INTR_STAT_OFS 0x0 21 + #define INTR_SET_OFS 0x8 22 + #define INTR_CLR_OFS 0x10 23 + 24 + #define MHU_LP_OFFSET 0x0 25 + #define MHU_HP_OFFSET 0x20 26 + #define MHU_SEC_OFFSET 0x200 27 + #define TX_REG_OFFSET 0x100 28 + 29 + #define MHU_CHANS 3 /* Secure, Non-Secure High and Low Priority */ 30 + #define MHU_CHAN_MAX 20 /* Max channels to save on unused RAM */ 31 + #define MHU_NUM_DOORBELLS 32 32 + 33 + struct mhu_db_link { 34 + unsigned int irq; 35 + void __iomem *tx_reg; 36 + void __iomem *rx_reg; 37 + }; 38 + 39 + struct arm_mhu { 40 + void __iomem *base; 41 + struct mhu_db_link mlink[MHU_CHANS]; 42 + struct mbox_controller mbox; 43 + struct device *dev; 44 + }; 45 + 46 + /** 47 + * ARM MHU Mailbox allocated channel information 48 + * 49 + * @mhu: Pointer to parent mailbox device 50 + * @pchan: Physical channel within which this doorbell resides in 51 + * @doorbell: doorbell number pertaining to this channel 52 + */ 53 + struct mhu_db_channel { 54 + struct arm_mhu *mhu; 55 + unsigned int pchan; 56 + unsigned int doorbell; 57 + }; 58 + 59 + static inline struct mbox_chan * 60 + mhu_db_mbox_to_channel(struct mbox_controller *mbox, unsigned int pchan, 61 + unsigned int doorbell) 62 + { 63 + int i; 64 + struct mhu_db_channel *chan_info; 65 + 66 + for (i = 0; i < mbox->num_chans; i++) { 67 + chan_info = mbox->chans[i].con_priv; 68 + if (chan_info && chan_info->pchan == pchan && 69 + chan_info->doorbell == doorbell) 70 + return &mbox->chans[i]; 71 + } 72 + 73 + return NULL; 74 + } 75 + 76 + static void mhu_db_mbox_clear_irq(struct mbox_chan *chan) 77 + { 78 + struct mhu_db_channel *chan_info = chan->con_priv; 79 + void __iomem *base = chan_info->mhu->mlink[chan_info->pchan].rx_reg; 80 + 81 + writel_relaxed(BIT(chan_info->doorbell), base + INTR_CLR_OFS); 82 + } 83 + 84 + static unsigned int mhu_db_mbox_irq_to_pchan_num(struct arm_mhu *mhu, int irq) 85 + { 86 + unsigned int pchan; 87 + 88 + for (pchan = 0; pchan < MHU_CHANS; pchan++) 89 + if (mhu->mlink[pchan].irq == irq) 90 + break; 91 + return pchan; 92 + } 93 + 94 + static struct mbox_chan * 95 + mhu_db_mbox_irq_to_channel(struct arm_mhu *mhu, unsigned int pchan) 96 + { 97 + unsigned long bits; 98 + unsigned int doorbell; 99 + struct mbox_chan *chan = NULL; 100 + struct mbox_controller *mbox = &mhu->mbox; 101 + void __iomem *base = mhu->mlink[pchan].rx_reg; 102 + 103 + bits = readl_relaxed(base + INTR_STAT_OFS); 104 + if (!bits) 105 + /* No IRQs fired in specified physical channel */ 106 + return NULL; 107 + 108 + /* An IRQ has fired, find the associated channel */ 109 + for (doorbell = 0; bits; doorbell++) { 110 + if (!test_and_clear_bit(doorbell, &bits)) 111 + continue; 112 + 113 + chan = mhu_db_mbox_to_channel(mbox, pchan, doorbell); 114 + if (chan) 115 + break; 116 + dev_err(mbox->dev, 117 + "Channel not registered: pchan: %d doorbell: %d\n", 118 + pchan, doorbell); 119 + } 120 + 121 + return chan; 122 + } 123 + 124 + static irqreturn_t mhu_db_mbox_rx_handler(int irq, void *data) 125 + { 126 + struct mbox_chan *chan; 127 + struct arm_mhu *mhu = data; 128 + unsigned int pchan = mhu_db_mbox_irq_to_pchan_num(mhu, irq); 129 + 130 + while (NULL != (chan = mhu_db_mbox_irq_to_channel(mhu, pchan))) { 131 + mbox_chan_received_data(chan, NULL); 132 + mhu_db_mbox_clear_irq(chan); 133 + } 134 + 135 + return IRQ_HANDLED; 136 + } 137 + 138 + static bool mhu_db_last_tx_done(struct mbox_chan *chan) 139 + { 140 + struct mhu_db_channel *chan_info = chan->con_priv; 141 + void __iomem *base = chan_info->mhu->mlink[chan_info->pchan].tx_reg; 142 + 143 + if (readl_relaxed(base + INTR_STAT_OFS) & BIT(chan_info->doorbell)) 144 + return false; 145 + 146 + return true; 147 + } 148 + 149 + static int mhu_db_send_data(struct mbox_chan *chan, void *data) 150 + { 151 + struct mhu_db_channel *chan_info = chan->con_priv; 152 + void __iomem *base = chan_info->mhu->mlink[chan_info->pchan].tx_reg; 153 + 154 + /* Send event to co-processor */ 155 + writel_relaxed(BIT(chan_info->doorbell), base + INTR_SET_OFS); 156 + 157 + return 0; 158 + } 159 + 160 + static int mhu_db_startup(struct mbox_chan *chan) 161 + { 162 + mhu_db_mbox_clear_irq(chan); 163 + return 0; 164 + } 165 + 166 + static void mhu_db_shutdown(struct mbox_chan *chan) 167 + { 168 + struct mhu_db_channel *chan_info = chan->con_priv; 169 + struct mbox_controller *mbox = &chan_info->mhu->mbox; 170 + int i; 171 + 172 + for (i = 0; i < mbox->num_chans; i++) 173 + if (chan == &mbox->chans[i]) 174 + break; 175 + 176 + if (mbox->num_chans == i) { 177 + dev_warn(mbox->dev, "Request to free non-existent channel\n"); 178 + return; 179 + } 180 + 181 + /* Reset channel */ 182 + mhu_db_mbox_clear_irq(chan); 183 + kfree(chan->con_priv); 184 + chan->con_priv = NULL; 185 + } 186 + 187 + static struct mbox_chan *mhu_db_mbox_xlate(struct mbox_controller *mbox, 188 + const struct of_phandle_args *spec) 189 + { 190 + struct arm_mhu *mhu = dev_get_drvdata(mbox->dev); 191 + struct mhu_db_channel *chan_info; 192 + struct mbox_chan *chan; 193 + unsigned int pchan = spec->args[0]; 194 + unsigned int doorbell = spec->args[1]; 195 + int i; 196 + 197 + /* Bounds checking */ 198 + if (pchan >= MHU_CHANS || doorbell >= MHU_NUM_DOORBELLS) { 199 + dev_err(mbox->dev, 200 + "Invalid channel requested pchan: %d doorbell: %d\n", 201 + pchan, doorbell); 202 + return ERR_PTR(-EINVAL); 203 + } 204 + 205 + /* Is requested channel free? */ 206 + chan = mhu_db_mbox_to_channel(mbox, pchan, doorbell); 207 + if (chan) { 208 + dev_err(mbox->dev, "Channel in use: pchan: %d doorbell: %d\n", 209 + pchan, doorbell); 210 + return ERR_PTR(-EBUSY); 211 + } 212 + 213 + /* Find the first free slot */ 214 + for (i = 0; i < mbox->num_chans; i++) 215 + if (!mbox->chans[i].con_priv) 216 + break; 217 + 218 + if (mbox->num_chans == i) { 219 + dev_err(mbox->dev, "No free channels left\n"); 220 + return ERR_PTR(-EBUSY); 221 + } 222 + 223 + chan = &mbox->chans[i]; 224 + 225 + chan_info = devm_kzalloc(mbox->dev, sizeof(*chan_info), GFP_KERNEL); 226 + if (!chan_info) 227 + return ERR_PTR(-ENOMEM); 228 + 229 + chan_info->mhu = mhu; 230 + chan_info->pchan = pchan; 231 + chan_info->doorbell = doorbell; 232 + 233 + chan->con_priv = chan_info; 234 + 235 + dev_dbg(mbox->dev, "mbox: created channel phys: %d doorbell: %d\n", 236 + pchan, doorbell); 237 + 238 + return chan; 239 + } 240 + 241 + static const struct mbox_chan_ops mhu_db_ops = { 242 + .send_data = mhu_db_send_data, 243 + .startup = mhu_db_startup, 244 + .shutdown = mhu_db_shutdown, 245 + .last_tx_done = mhu_db_last_tx_done, 246 + }; 247 + 248 + static int mhu_db_probe(struct amba_device *adev, const struct amba_id *id) 249 + { 250 + u32 cell_count; 251 + int i, err, max_chans; 252 + struct arm_mhu *mhu; 253 + struct mbox_chan *chans; 254 + struct device *dev = &adev->dev; 255 + struct device_node *np = dev->of_node; 256 + int mhu_reg[MHU_CHANS] = { 257 + MHU_LP_OFFSET, MHU_HP_OFFSET, MHU_SEC_OFFSET, 258 + }; 259 + 260 + if (!of_device_is_compatible(np, "arm,mhu-doorbell")) 261 + return -ENODEV; 262 + 263 + err = of_property_read_u32(np, "#mbox-cells", &cell_count); 264 + if (err) { 265 + dev_err(dev, "failed to read #mbox-cells in '%pOF'\n", np); 266 + return err; 267 + } 268 + 269 + if (cell_count == 2) { 270 + max_chans = MHU_CHAN_MAX; 271 + } else { 272 + dev_err(dev, "incorrect value of #mbox-cells in '%pOF'\n", np); 273 + return -EINVAL; 274 + } 275 + 276 + mhu = devm_kzalloc(dev, sizeof(*mhu), GFP_KERNEL); 277 + if (!mhu) 278 + return -ENOMEM; 279 + 280 + mhu->base = devm_ioremap_resource(dev, &adev->res); 281 + if (IS_ERR(mhu->base)) { 282 + dev_err(dev, "ioremap failed\n"); 283 + return PTR_ERR(mhu->base); 284 + } 285 + 286 + chans = devm_kcalloc(dev, max_chans, sizeof(*chans), GFP_KERNEL); 287 + if (!chans) 288 + return -ENOMEM; 289 + 290 + mhu->dev = dev; 291 + mhu->mbox.dev = dev; 292 + mhu->mbox.chans = chans; 293 + mhu->mbox.num_chans = max_chans; 294 + mhu->mbox.txdone_irq = false; 295 + mhu->mbox.txdone_poll = true; 296 + mhu->mbox.txpoll_period = 1; 297 + 298 + mhu->mbox.of_xlate = mhu_db_mbox_xlate; 299 + amba_set_drvdata(adev, mhu); 300 + 301 + mhu->mbox.ops = &mhu_db_ops; 302 + 303 + err = devm_mbox_controller_register(dev, &mhu->mbox); 304 + if (err) { 305 + dev_err(dev, "Failed to register mailboxes %d\n", err); 306 + return err; 307 + } 308 + 309 + for (i = 0; i < MHU_CHANS; i++) { 310 + int irq = mhu->mlink[i].irq = adev->irq[i]; 311 + 312 + if (irq <= 0) { 313 + dev_dbg(dev, "No IRQ found for Channel %d\n", i); 314 + continue; 315 + } 316 + 317 + mhu->mlink[i].rx_reg = mhu->base + mhu_reg[i]; 318 + mhu->mlink[i].tx_reg = mhu->mlink[i].rx_reg + TX_REG_OFFSET; 319 + 320 + err = devm_request_threaded_irq(dev, irq, NULL, 321 + mhu_db_mbox_rx_handler, 322 + IRQF_ONESHOT, "mhu_db_link", mhu); 323 + if (err) { 324 + dev_err(dev, "Can't claim IRQ %d\n", irq); 325 + mbox_controller_unregister(&mhu->mbox); 326 + return err; 327 + } 328 + } 329 + 330 + dev_info(dev, "ARM MHU Doorbell mailbox registered\n"); 331 + return 0; 332 + } 333 + 334 + static struct amba_id mhu_ids[] = { 335 + { 336 + .id = 0x1bb098, 337 + .mask = 0xffffff, 338 + }, 339 + { 0, 0 }, 340 + }; 341 + MODULE_DEVICE_TABLE(amba, mhu_ids); 342 + 343 + static struct amba_driver arm_mhu_db_driver = { 344 + .drv = { 345 + .name = "mhu-doorbell", 346 + }, 347 + .id_table = mhu_ids, 348 + .probe = mhu_db_probe, 349 + }; 350 + module_amba_driver(arm_mhu_db_driver); 351 + 352 + MODULE_LICENSE("GPL v2"); 353 + MODULE_DESCRIPTION("ARM MHU Doorbell Driver"); 354 + MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+3 -3
drivers/mailbox/bcm-pdc-mailbox.c
··· 962 962 * a DMA receive interrupt. Reenables the receive interrupt. 963 963 * @data: PDC state structure 964 964 */ 965 - static void pdc_tasklet_cb(unsigned long data) 965 + static void pdc_tasklet_cb(struct tasklet_struct *t) 966 966 { 967 - struct pdc_state *pdcs = (struct pdc_state *)data; 967 + struct pdc_state *pdcs = from_tasklet(pdcs, t, rx_tasklet); 968 968 969 969 pdc_receive(pdcs); 970 970 ··· 1589 1589 pdc_hw_init(pdcs); 1590 1590 1591 1591 /* Init tasklet for deferred DMA rx processing */ 1592 - tasklet_init(&pdcs->rx_tasklet, pdc_tasklet_cb, (unsigned long)pdcs); 1592 + tasklet_setup(&pdcs->rx_tasklet, pdc_tasklet_cb); 1593 1593 1594 1594 err = pdc_interrupts_init(pdcs); 1595 1595 if (err)
+7 -5
drivers/mailbox/mailbox.c
··· 82 82 exit: 83 83 spin_unlock_irqrestore(&chan->lock, flags); 84 84 85 - if (!err && (chan->txdone_method & TXDONE_BY_POLL)) 86 - /* kick start the timer immediately to avoid delays */ 87 - hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL); 85 + /* kick start the timer immediately to avoid delays */ 86 + if (!err && (chan->txdone_method & TXDONE_BY_POLL)) { 87 + /* but only if not already active */ 88 + if (!hrtimer_active(&chan->mbox->poll_hrt)) 89 + hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL); 90 + } 88 91 } 89 92 90 93 static void tx_tick(struct mbox_chan *chan, int r) ··· 125 122 struct mbox_chan *chan = &mbox->chans[i]; 126 123 127 124 if (chan->active_req && chan->cl) { 125 + resched = true; 128 126 txdone = chan->mbox->ops->last_tx_done(chan); 129 127 if (txdone) 130 128 tx_tick(chan, 0); 131 - else 132 - resched = true; 133 129 } 134 130 } 135 131
+3 -5
drivers/mailbox/mtk-cmdq-mailbox.c
··· 69 69 struct cmdq { 70 70 struct mbox_controller mbox; 71 71 void __iomem *base; 72 - u32 irq; 72 + int irq; 73 73 u32 thread_nr; 74 74 u32 irq_mask; 75 75 struct cmdq_thread *thread; ··· 525 525 } 526 526 527 527 cmdq->irq = platform_get_irq(pdev, 0); 528 - if (!cmdq->irq) { 529 - dev_err(dev, "failed to get irq\n"); 530 - return -EINVAL; 531 - } 528 + if (cmdq->irq < 0) 529 + return cmdq->irq; 532 530 533 531 plat_data = (struct gce_plat *)of_device_get_match_data(dev); 534 532 if (!plat_data) {