diff options
Diffstat (limited to 'kernel/xpp/card_global.c')
-rw-r--r-- | kernel/xpp/card_global.c | 98 |
1 files changed, 55 insertions, 43 deletions
diff --git a/kernel/xpp/card_global.c b/kernel/xpp/card_global.c index d3a7a66..88b9f60 100644 --- a/kernel/xpp/card_global.c +++ b/kernel/xpp/card_global.c @@ -40,6 +40,7 @@ extern int debug; /*---------------- GLOBAL PROC handling -----------------------------------*/ +#ifdef OLD_PROC static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = 0; @@ -51,6 +52,8 @@ static int proc_xpd_register_read(char *page, char **start, off_t off, int count if(!xpd) return -ENODEV; + XPD_NOTICE(xpd, "%s: DEPRECATED: %s[%d] read from /proc interface instead of /sys\n", + __FUNCTION__, current->comm, current->tgid); spin_lock_irqsave(&xpd->lock, flags); info = &xpd->last_reply; len += sprintf(page + len, "# Writing bad data into this file may damage your hardware!\n"); @@ -88,6 +91,7 @@ static int proc_xpd_register_read(char *page, char **start, off_t off, int count len = 0; return len; } +#endif static int parse_hexbyte(const char *buf) { @@ -289,7 +293,7 @@ out: return ret; } -static int parse_chip_command(xpd_t *xpd, char *cmdline) +int parse_chip_command(xpd_t *xpd, char *cmdline) { xbus_t *xbus; int ret = -EBADR; @@ -303,8 +307,9 @@ static int parse_chip_command(xpd_t *xpd, char *cmdline) BUG_ON(!xpd); xbus = xpd->xbus; - if(!XBUS_GET(xbus)) { - XBUS_DBG(GENERAL, xbus, "Dropped packet. Is shutting down.\n"); + if(XBUS_IS(xbus, DISCONNECTED)) { + XBUS_DBG(GENERAL, xbus, "Dropped packet. In state %s.\n", + xbus_statename(XBUS_STATE(xbus))); return -EBUSY; } strlcpy(buf, cmdline, MAX_PROC_WRITE); /* Save a copy */ @@ -335,11 +340,10 @@ static int parse_chip_command(xpd_t *xpd, char *cmdline) else ret = 0; /* empty command - no op */ out: - XBUS_PUT(xbus); return ret; } - +#ifdef OLD_PROC static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data) { xpd_t *xpd = data; @@ -350,6 +354,8 @@ static int proc_xpd_register_write(struct file *file, const char __user *buffer, if(!xpd) return -ENODEV; + XPD_NOTICE(xpd, "%s: DEPRECATED: %s[%d] wrote to /proc interface instead of /sys\n", + __FUNCTION__, current->comm, current->tgid); for(i = 0; i < count; /* noop */) { for(p = buf; p < buf + MAX_PROC_WRITE; p++) { /* read a line */ if(i >= count) @@ -368,7 +374,9 @@ static int proc_xpd_register_write(struct file *file, const char __user *buffer, XPD_NOTICE(xpd, "Failed writing command: '%s'\n", buf); return ret; } - msleep(1); /* don't overflow command queue */ + /* Don't flood command_queue */ + if(xframe_queue_count(&xpd->xbus->command_queue) > 5) + msleep(6); } return count; } @@ -405,6 +413,7 @@ err: chip_proc_remove(xbus, xpd); return -EINVAL; } +#endif /*---------------- GLOBAL Protocol Commands -------------------------------*/ @@ -415,7 +424,7 @@ static void global_packet_dump(const char *msg, xpacket_t *pack); /* 0x07 */ HOSTCMD(GLOBAL, AB_REQUEST) { - int ret = 0; + int ret = -ENODEV; xframe_t *xframe; xpacket_t *pack; @@ -427,7 +436,8 @@ static void global_packet_dump(const char *msg, xpacket_t *pack); RPACKET_FIELD(pack, GLOBAL, AB_REQUEST, rev) = XPP_PROTOCOL_VERSION; RPACKET_FIELD(pack, GLOBAL, AB_REQUEST, reserved) = 0; XBUS_DBG(DEVICES, xbus, "Protocol Version %d\n", XPP_PROTOCOL_VERSION); - ret = send_cmd_frame(xbus, xframe); + if(xbus_setstate(xbus, XBUS_STATE_SENT_REQUEST)) + ret = send_cmd_frame(xbus, xframe); return ret; } @@ -474,6 +484,12 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno, dump_reg_cmd("REG_REQ", 1, xbus, xpd->addr.unit, reg_cmd->portnum, reg_cmd); dump_packet("REG_REQ", pack, 1); } + if(!xframe->usec_towait) { /* default processing time of SPI */ + if(subreg) + xframe->usec_towait = 2000; + else + xframe->usec_towait = 1000; + } ret = send_cmd_frame(xbus, xframe); return ret; } @@ -590,6 +606,10 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION) /* 0x08 */ ret = -EPROTO; goto proto_err; } + if(!xbus_setstate(xbus, XBUS_STATE_RECVD_DESC)) { + ret = -EPROTO; + goto proto_err; + } XBUS_INFO(xbus, "DESCRIPTOR: %d cards, protocol revision %d\n", count_units, rev); xbus->revision = rev; if(!worker) { @@ -631,19 +651,8 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION) /* 0x08 */ list_add_tail(&card_desc->card_list, &worker->card_list); spin_unlock_irqrestore(&worker->worker_lock, flags); } - /* Initialize the work. (adapt to kernel API changes). */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) - INIT_WORK(&worker->xpds_init_work, xbus_populate); -#else - INIT_WORK(&worker->xpds_init_work, xbus_populate, worker); -#endif - xbus = get_xbus(xbus->num); /* released in xbus_populate() */ - BUG_ON(!xbus); - /* Now send it */ - if(!queue_work(worker->wq, &worker->xpds_init_work)) { - XBUS_ERR(xbus, "Failed to queue xpd initialization work\n"); + if(!xbus_process_worker(xbus)) return -ENODEV; - } return 0; proto_err: dump_packet("AB_DESCRIPTION", pack, DBG_ANY); @@ -690,34 +699,24 @@ HANDLER_DEF(GLOBAL, SYNC_REPLY) HANDLER_DEF(GLOBAL, ERROR_CODE) { - byte errorcode; char tmp_name[TMP_NAME_LEN]; static long rate_limit; - const char *msg; - const static char *fw_messages[] = { - [1] = "Packet too short", - [2] = "Len field is too small", - [3] = "Premature packet end", - [4] = "Invalid op code", - [5] = "Invalid packet len", - [6] = "SPI fifo full", - }; + byte category_code; + byte errorbits; BUG_ON(!xbus); if((rate_limit++ % 5003) > 200) return 0; - errorcode = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, errorcode); - msg = (errorcode < ARRAY_SIZE(fw_messages)) - ? fw_messages[errorcode] - : "UNKNOWN CODE"; + category_code = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, category_code); + errorbits = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, errorbits); if(!xpd) { snprintf(tmp_name, TMP_NAME_LEN, "%s(%1d%1d)", xbus->busname, XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack)); } else { snprintf(tmp_name, TMP_NAME_LEN, "%s/%s", xbus->busname, xpd->xpdname); } - NOTICE("%s: FIRMWARE: %s CODE = 0x%X (%s) (rate_limit=%ld)\n", - tmp_name, cmd->name, errorcode, msg, rate_limit); + NOTICE("%s: FIRMWARE %s: category=%d errorbits=0x%02X (rate_limit=%ld)\n", + tmp_name, cmd->name, category_code, errorbits, rate_limit); dump_packet("FIRMWARE: ", pack, 1); /* * FIXME: Should implement an error recovery plan @@ -755,19 +754,21 @@ static void global_packet_dump(const char *msg, xpacket_t *pack) } #define MAX_ENV_STR 40 -#define MAX_PATH_STR 60 +#define MAX_PATH_STR 128 int run_initialize_registers(xpd_t *xpd) { int ret; xbus_t *xbus; char busstr[MAX_ENV_STR]; + char busnumstr[MAX_ENV_STR]; char unitstr[MAX_ENV_STR]; char subunitsstr[MAX_ENV_STR]; char typestr[MAX_ENV_STR]; char directionstr[MAX_ENV_STR]; char revstr[MAX_ENV_STR]; char connectorstr[MAX_ENV_STR]; + char xbuslabel[MAX_ENV_STR]; char init_card[MAX_PATH_STR]; byte direction_mask; int i; @@ -777,12 +778,14 @@ int run_initialize_registers(xpd_t *xpd) }; char *envp[] = { busstr, + busnumstr, unitstr, subunitsstr, typestr, directionstr, revstr, connectorstr, + xbuslabel, NULL }; @@ -792,6 +795,10 @@ int run_initialize_registers(xpd_t *xpd) XPD_NOTICE(xpd, "Missing initdir parameter\n"); return -EINVAL; } + if(!xpd_setstate(xpd, XPD_STATE_INIT_REGS)) { + ret = -EINVAL; + goto err; + } direction_mask = 0; for(i = 0; i < xpd->subunits; i++) { xpd_t *su = xpd_byaddr(xbus, xpd->addr.unit, i); @@ -805,20 +812,25 @@ int run_initialize_registers(xpd_t *xpd) direction_mask |= (su->direction == TO_PHONE) ? BIT(i) : 0; } snprintf(busstr, MAX_ENV_STR, "XBUS_NAME=%s", xbus->busname); + snprintf(busnumstr, MAX_ENV_STR, "XBUS_NUMBER=%d", xbus->num); snprintf(unitstr, MAX_ENV_STR, "UNIT_NUMBER=%d", xpd->addr.unit); snprintf(typestr, MAX_ENV_STR, "UNIT_TYPE=%d", xpd->type); snprintf(subunitsstr, MAX_ENV_STR, "UNIT_SUBUNITS=%d", xpd->subunits); snprintf(directionstr, MAX_ENV_STR, "UNIT_SUBUNITS_DIR=%d", direction_mask); snprintf(revstr, MAX_ENV_STR, "XBUS_REVISION=%d", xbus->revision); - snprintf(connectorstr, MAX_ENV_STR, "XBUS_CONNECTOR=%s", xbus->location); + snprintf(connectorstr, MAX_ENV_STR, "XBUS_CONNECTOR=%s", xbus->connector); + snprintf(xbuslabel, MAX_ENV_STR, "XBUS_LABEL=%s", xbus->label); if(snprintf(init_card, MAX_PATH_STR, "%s/init_card_%d_%d", initdir, xpd->type, xbus->revision) > MAX_PATH_STR) { XPD_NOTICE(xpd, "Cannot initialize. pathname is longer than %d characters.\n", MAX_PATH_STR); - return -E2BIG; + ret = -E2BIG; + goto err; } - if(!XBUS_GET(xbus)) { - XBUS_ERR(xbus, "Skipped register initialization. XBUS is going down\n"); - return -ENODEV; + if(!XBUS_IS(xbus, RECVD_DESC)) { + XBUS_ERR(xbus, "Skipped register initialization. In state %s.\n", + xbus_statename(XBUS_STATE(xbus))); + ret = -ENODEV; + goto err; } XPD_DBG(DEVICES, xpd, "running '%s' for type=%d revision=%d\n", init_card, xpd->type, xbus->revision); @@ -841,7 +853,7 @@ int run_initialize_registers(xpd_t *xpd) } ret = -EINVAL; } - XBUS_PUT(xbus); +err: return ret; } |