#if !ACX_DEBUG int acxpci_s_issue_cmd_timeo(acx_device_t * adev, unsigned int cmd, void *buffer, unsigned buflen, unsigned cmd_timeout) { #else int acxpci_s_issue_cmd_timeo_debug(acx_device_t * adev, unsigned cmd, void *buffer, unsigned buflen, unsigned cmd_timeout, const char *cmdstr) { unsigned long start = jiffies; #endif const char *devname; unsigned counter; u16 irqtype; u16 cmd_status; unsigned long timeout; unsigned long flags; FN_ENTER; devname = wiphy_name(adev->ieee->wiphy); if (!devname || !devname[0] || devname[4] == '%') devname = "acx"; breakpoint(); log(L_CTL, FUNC "(cmd:%s,buflen:%u,timeout:%ums,type:0x%04X)\n", cmdstr, buflen, cmd_timeout, buffer ? le16_to_cpu(((acx_ie_generic_t *) buffer)->type) : -1); breakpoint(); if (!(adev->dev_state_mask & ACX_STATE_FW_LOADED)) { printk("%s: " FUNC "(): firmware is not loaded yet, " "cannot execute commands!\n", devname); goto bad; } breakpoint(); if ((acx_debug & L_DEBUG) && (cmd != ACX1xx_CMD_INTERROGATE)) { printk("input buffer (len=%u):\n", buflen); acx_dump_bytes(buffer, buflen); } breakpoint(); /* wait for firmware to become idle for our command submission */ timeout = HZ / 5; counter = (timeout * 1000 / HZ) - 1; /* in ms */ timeout += jiffies; do { cmd_status = acxpci_read_cmd_type_status(adev); /* Test for IDLE state */ if (!cmd_status) break; if (counter % 8 == 0) { if (time_after(jiffies, timeout)) { counter = 0; break; } /* we waited 8 iterations, no luck. Sleep 8 ms */ acx_s_mwait(8); } } while (likely(--counter)); breakpoint(); if (!counter) { /* the card doesn't get idle, we're in trouble */ printk("%s: " FUNC "(): cmd_status is not IDLE: 0x%04X!=0\n", devname, cmd_status); goto bad; } else if (counter < 190) { /* if waited >10ms... */ log(L_CTL | L_DEBUG, FUNC "(): waited for IDLE %dms. " "Please report\n", 199 - counter); } breakpoint(); /* now write the parameters of the command if needed */ if (buffer && buflen) { /* if it's an INTERROGATE command, just pass the length * of parameters to read, as data */ #if CMD_DISCOVERY if (cmd == ACX1xx_CMD_INTERROGATE) memset_io(adev->cmd_area + 4, 0xAA, buflen); #endif /* adev->cmd_area points to PCI device's memory, not to RAM! */ memcpy_toio(adev->cmd_area + 4, buffer, (cmd == ACX1xx_CMD_INTERROGATE) ? 4 : buflen); } breakpoint(); /* now write the actual command type */ acxpci_write_cmd_type_status(adev, cmd, 0); breakpoint(); /* execute command */ write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_CMD); breakpoint(); write_flush(adev); breakpoint(); /* wait for firmware to process command */