18722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com/* 28722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* Filename: cregs.c 38722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* 48722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* 58722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* Authors: Joshua Morris <josh.h.morris@us.ibm.com> 68722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* Philip Kelleher <pjk1939@linux.vnet.ibm.com> 78722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* 88722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* (C) Copyright 2013 IBM Corporation 98722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* 108722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* This program is free software; you can redistribute it and/or 118722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* modify it under the terms of the GNU General Public License as 128722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* published by the Free Software Foundation; either version 2 of the 138722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* License, or (at your option) any later version. 148722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* 158722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* This program is distributed in the hope that it will be useful, but 168722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* WITHOUT ANY WARRANTY; without even the implied warranty of 178722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 188722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* General Public License for more details. 198722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* 208722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* You should have received a copy of the GNU General Public License 218722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* along with this program; if not, write to the Free Software Foundation, 228722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 238722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com*/ 248722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 258722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com#include <linux/completion.h> 268722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com#include <linux/slab.h> 278722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 288722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com#include "rsxx_priv.h" 298722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 308722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com#define CREG_TIMEOUT_MSEC 10000 318722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 328722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comtypedef void (*creg_cmd_cb)(struct rsxx_cardinfo *card, 338722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct creg_cmd *cmd, 348722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int st); 358722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 368722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comstruct creg_cmd { 378722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct list_head list; 388722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com creg_cmd_cb cb; 398722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com void *cb_private; 408722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int op; 418722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int addr; 428722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int cnt8; 438722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com void *buf; 448722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int stream; 458722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int status; 468722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com}; 478722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 488722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comstatic struct kmem_cache *creg_cmd_pool; 498722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 508722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 518722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com/*------------ Private Functions --------------*/ 528722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 538722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com#if defined(__LITTLE_ENDIAN) 548722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com#define LITTLE_ENDIAN 1 558722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com#elif defined(__BIG_ENDIAN) 568722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com#define LITTLE_ENDIAN 0 578722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com#else 588722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com#error Unknown endianess!!! Aborting... 598722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com#endif 608722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 61c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleherstatic int copy_to_creg_data(struct rsxx_cardinfo *card, 628722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int cnt8, 638722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com void *buf, 648722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int stream) 658722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 668722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int i = 0; 678722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com u32 *data = buf; 688722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 69c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher if (unlikely(card->eeh_state)) 70c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher return -EIO; 71c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher 728722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com for (i = 0; cnt8 > 0; i++, cnt8 -= 4) { 738722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com /* 748722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * Firmware implementation makes it necessary to byte swap on 758722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * little endian processors. 768722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com */ 778722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (LITTLE_ENDIAN && stream) 788722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com iowrite32be(data[i], card->regmap + CREG_DATA(i)); 798722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com else 808722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com iowrite32(data[i], card->regmap + CREG_DATA(i)); 818722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 82c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher 83c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher return 0; 848722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 858722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 868722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 87c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleherstatic int copy_from_creg_data(struct rsxx_cardinfo *card, 888722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int cnt8, 898722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com void *buf, 908722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int stream) 918722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 928722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int i = 0; 938722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com u32 *data = buf; 948722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 95c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher if (unlikely(card->eeh_state)) 96c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher return -EIO; 97c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher 988722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com for (i = 0; cnt8 > 0; i++, cnt8 -= 4) { 998722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com /* 1008722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * Firmware implementation makes it necessary to byte swap on 1018722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * little endian processors. 1028722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com */ 1038722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (LITTLE_ENDIAN && stream) 1048722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com data[i] = ioread32be(card->regmap + CREG_DATA(i)); 1058722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com else 1068722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com data[i] = ioread32(card->regmap + CREG_DATA(i)); 1078722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 108c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher 109c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher return 0; 1108722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 1118722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 1128722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comstatic void creg_issue_cmd(struct rsxx_cardinfo *card, struct creg_cmd *cmd) 1138722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 114c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher int st; 115c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher 116c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher if (unlikely(card->eeh_state)) 117c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher return; 118c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher 1198722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com iowrite32(cmd->addr, card->regmap + CREG_ADD); 1208722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com iowrite32(cmd->cnt8, card->regmap + CREG_CNT); 1218722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 1228722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (cmd->op == CREG_OP_WRITE) { 123c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher if (cmd->buf) { 124c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher st = copy_to_creg_data(card, cmd->cnt8, 125c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher cmd->buf, cmd->stream); 126c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher if (st) 127c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher return; 128c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher } 1298722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 1308722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 131c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher if (unlikely(card->eeh_state)) 132c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher return; 133c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher 1348722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com /* Setting the valid bit will kick off the command. */ 1358722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com iowrite32(cmd->op, card->regmap + CREG_CMD); 1368722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 1378722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 1388722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comstatic void creg_kick_queue(struct rsxx_cardinfo *card) 1398722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 1408722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (card->creg_ctrl.active || list_empty(&card->creg_ctrl.queue)) 1418722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return; 1428722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 1438722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->creg_ctrl.active = 1; 1448722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->creg_ctrl.active_cmd = list_first_entry(&card->creg_ctrl.queue, 1458722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct creg_cmd, list); 1468722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com list_del(&card->creg_ctrl.active_cmd->list); 1478722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->creg_ctrl.q_depth--; 1488722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 1498722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com /* 1508722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * We have to set the timer before we push the new command. Otherwise, 1518722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * we could create a race condition that would occur if the timer 1528722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * was not canceled, and expired after the new command was pushed, 1538722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * but before the command was issued to hardware. 1548722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com */ 1558722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com mod_timer(&card->creg_ctrl.cmd_timer, 1568722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com jiffies + msecs_to_jiffies(CREG_TIMEOUT_MSEC)); 1578722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 1588722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com creg_issue_cmd(card, card->creg_ctrl.active_cmd); 1598722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 1608722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 1618722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comstatic int creg_queue_cmd(struct rsxx_cardinfo *card, 1628722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int op, 1638722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int addr, 1648722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int cnt8, 1658722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com void *buf, 1668722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int stream, 1678722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com creg_cmd_cb callback, 1688722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com void *cb_private) 1698722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 1708722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct creg_cmd *cmd; 1718722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 1728722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com /* Don't queue stuff up if we're halted. */ 1738722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (unlikely(card->halt)) 1748722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return -EINVAL; 1758722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 1768722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (card->creg_ctrl.reset) 1778722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return -EAGAIN; 1788722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 1798722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (cnt8 > MAX_CREG_DATA8) 1808722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return -EINVAL; 1818722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 1828722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd = kmem_cache_alloc(creg_cmd_pool, GFP_KERNEL); 1838722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (!cmd) 1848722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return -ENOMEM; 1858722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 1868722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com INIT_LIST_HEAD(&cmd->list); 1878722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 1888722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd->op = op; 1898722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd->addr = addr; 1908722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd->cnt8 = cnt8; 1918722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd->buf = buf; 1928722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd->stream = stream; 1938722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd->cb = callback; 1948722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd->cb_private = cb_private; 1958722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd->status = 0; 1968722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 19703ac03a8971bd7e9f8c8b20a309b61beaf154d60Philip J Kelleher spin_lock_bh(&card->creg_ctrl.lock); 1988722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com list_add_tail(&cmd->list, &card->creg_ctrl.queue); 1998722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->creg_ctrl.q_depth++; 2008722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com creg_kick_queue(card); 20103ac03a8971bd7e9f8c8b20a309b61beaf154d60Philip J Kelleher spin_unlock_bh(&card->creg_ctrl.lock); 2028722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 2038722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return 0; 2048722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 2058722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 2068722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comstatic void creg_cmd_timed_out(unsigned long data) 2078722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 2088722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct rsxx_cardinfo *card = (struct rsxx_cardinfo *) data; 2098722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct creg_cmd *cmd; 2108722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 21103ac03a8971bd7e9f8c8b20a309b61beaf154d60Philip J Kelleher spin_lock(&card->creg_ctrl.lock); 21203ac03a8971bd7e9f8c8b20a309b61beaf154d60Philip J Kelleher cmd = card->creg_ctrl.active_cmd; 21303ac03a8971bd7e9f8c8b20a309b61beaf154d60Philip J Kelleher card->creg_ctrl.active_cmd = NULL; 21403ac03a8971bd7e9f8c8b20a309b61beaf154d60Philip J Kelleher spin_unlock(&card->creg_ctrl.lock); 21503ac03a8971bd7e9f8c8b20a309b61beaf154d60Philip J Kelleher 2168722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (cmd == NULL) { 2178722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->creg_ctrl.creg_stats.creg_timeout++; 2188722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_warn(CARD_TO_DEV(card), 2198722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com "No active command associated with timeout!\n"); 2208722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return; 2218722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 2228722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 2238722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (cmd->cb) 2248722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd->cb(card, cmd, -ETIMEDOUT); 2258722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 2268722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com kmem_cache_free(creg_cmd_pool, cmd); 2278722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 228c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher 229c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher spin_lock(&card->creg_ctrl.lock); 2308722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->creg_ctrl.active = 0; 2318722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com creg_kick_queue(card); 232c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher spin_unlock(&card->creg_ctrl.lock); 2338722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 2348722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 2358722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 2368722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comstatic void creg_cmd_done(struct work_struct *work) 2378722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 2388722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct rsxx_cardinfo *card; 2398722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct creg_cmd *cmd; 2408722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int st = 0; 2418722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 2428722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card = container_of(work, struct rsxx_cardinfo, 2438722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com creg_ctrl.done_work); 2448722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 2458722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com /* 2468722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * The timer could not be cancelled for some reason, 2478722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * race to pop the active command. 2488722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com */ 2498722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (del_timer_sync(&card->creg_ctrl.cmd_timer) == 0) 2508722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->creg_ctrl.creg_stats.failed_cancel_timer++; 2518722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 25203ac03a8971bd7e9f8c8b20a309b61beaf154d60Philip J Kelleher spin_lock_bh(&card->creg_ctrl.lock); 25303ac03a8971bd7e9f8c8b20a309b61beaf154d60Philip J Kelleher cmd = card->creg_ctrl.active_cmd; 25403ac03a8971bd7e9f8c8b20a309b61beaf154d60Philip J Kelleher card->creg_ctrl.active_cmd = NULL; 25503ac03a8971bd7e9f8c8b20a309b61beaf154d60Philip J Kelleher spin_unlock_bh(&card->creg_ctrl.lock); 25603ac03a8971bd7e9f8c8b20a309b61beaf154d60Philip J Kelleher 2578722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (cmd == NULL) { 2588722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_err(CARD_TO_DEV(card), 2598722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com "Spurious creg interrupt!\n"); 2608722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return; 2618722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 2628722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 2638722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->creg_ctrl.creg_stats.stat = ioread32(card->regmap + CREG_STAT); 2648722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd->status = card->creg_ctrl.creg_stats.stat; 2658722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if ((cmd->status & CREG_STAT_STATUS_MASK) == 0) { 2668722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_err(CARD_TO_DEV(card), 2678722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com "Invalid status on creg command\n"); 2688722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com /* 2698722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * At this point we're probably reading garbage from HW. Don't 2708722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * do anything else that could mess up the system and let 2718722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * the sync function return an error. 2728722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com */ 2738722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com st = -EIO; 2748722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com goto creg_done; 2758722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } else if (cmd->status & CREG_STAT_ERROR) { 2768722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com st = -EIO; 2778722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 2788722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 2798722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if ((cmd->op == CREG_OP_READ)) { 2808722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int cnt8 = ioread32(card->regmap + CREG_CNT); 2818722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 2828722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com /* Paranoid Sanity Checks */ 2838722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (!cmd->buf) { 2848722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_err(CARD_TO_DEV(card), 2858722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com "Buffer not given for read.\n"); 2868722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com st = -EIO; 2878722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com goto creg_done; 2888722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 2898722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (cnt8 != cmd->cnt8) { 2908722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_err(CARD_TO_DEV(card), 2918722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com "count mismatch\n"); 2928722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com st = -EIO; 2938722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com goto creg_done; 2948722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 2958722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 296c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher st = copy_from_creg_data(card, cnt8, cmd->buf, cmd->stream); 2978722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 2988722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 2998722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comcreg_done: 3008722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (cmd->cb) 3018722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd->cb(card, cmd, st); 3028722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 3038722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com kmem_cache_free(creg_cmd_pool, cmd); 3048722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 30503ac03a8971bd7e9f8c8b20a309b61beaf154d60Philip J Kelleher spin_lock_bh(&card->creg_ctrl.lock); 3068722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->creg_ctrl.active = 0; 3078722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com creg_kick_queue(card); 30803ac03a8971bd7e9f8c8b20a309b61beaf154d60Philip J Kelleher spin_unlock_bh(&card->creg_ctrl.lock); 3098722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 3108722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 3118722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comstatic void creg_reset(struct rsxx_cardinfo *card) 3128722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 3138722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct creg_cmd *cmd = NULL; 3148722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct creg_cmd *tmp; 3158722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned long flags; 3168722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 317c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher /* 318c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher * mutex_trylock is used here because if reset_lock is taken then a 319c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher * reset is already happening. So, we can just go ahead and return. 320c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher */ 3218722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (!mutex_trylock(&card->creg_ctrl.reset_lock)) 3228722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return; 3238722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 3248722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->creg_ctrl.reset = 1; 3258722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com spin_lock_irqsave(&card->irq_lock, flags); 3268722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com rsxx_disable_ier_and_isr(card, CR_INTR_CREG | CR_INTR_EVENT); 3278722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com spin_unlock_irqrestore(&card->irq_lock, flags); 3288722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 3298722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_warn(CARD_TO_DEV(card), 3308722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com "Resetting creg interface for recovery\n"); 3318722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 3328722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com /* Cancel outstanding commands */ 33303ac03a8971bd7e9f8c8b20a309b61beaf154d60Philip J Kelleher spin_lock_bh(&card->creg_ctrl.lock); 3348722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) { 3358722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com list_del(&cmd->list); 3368722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->creg_ctrl.q_depth--; 3378722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (cmd->cb) 3388722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd->cb(card, cmd, -ECANCELED); 3398722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com kmem_cache_free(creg_cmd_pool, cmd); 3408722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 3418722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 3428722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd = card->creg_ctrl.active_cmd; 3438722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->creg_ctrl.active_cmd = NULL; 3448722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (cmd) { 3458722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (timer_pending(&card->creg_ctrl.cmd_timer)) 3468722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com del_timer_sync(&card->creg_ctrl.cmd_timer); 3478722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 3488722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (cmd->cb) 3498722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd->cb(card, cmd, -ECANCELED); 3508722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com kmem_cache_free(creg_cmd_pool, cmd); 3518722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 3528722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->creg_ctrl.active = 0; 3538722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 35403ac03a8971bd7e9f8c8b20a309b61beaf154d60Philip J Kelleher spin_unlock_bh(&card->creg_ctrl.lock); 3558722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 3568722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->creg_ctrl.reset = 0; 3578722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com spin_lock_irqsave(&card->irq_lock, flags); 3588722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com rsxx_enable_ier_and_isr(card, CR_INTR_CREG | CR_INTR_EVENT); 3598722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com spin_unlock_irqrestore(&card->irq_lock, flags); 3608722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 3618722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com mutex_unlock(&card->creg_ctrl.reset_lock); 3628722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 3638722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 3648722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com/* Used for synchronous accesses */ 3658722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comstruct creg_completion { 3668722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct completion *cmd_done; 3678722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int st; 3688722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com u32 creg_status; 3698722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com}; 3708722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 3718722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comstatic void creg_cmd_done_cb(struct rsxx_cardinfo *card, 3728722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct creg_cmd *cmd, 3738722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int st) 3748722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 3758722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct creg_completion *cmd_completion; 3768722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 377c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher cmd_completion = cmd->cb_private; 3788722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com BUG_ON(!cmd_completion); 3798722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 3808722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd_completion->st = st; 3818722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd_completion->creg_status = cmd->status; 3828722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com complete(cmd_completion->cmd_done); 3838722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 3848722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 3858722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comstatic int __issue_creg_rw(struct rsxx_cardinfo *card, 3868722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int op, 3878722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int addr, 3888722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int cnt8, 3898722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com void *buf, 3908722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int stream, 3918722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int *hw_stat) 3928722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 3938722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com DECLARE_COMPLETION_ONSTACK(cmd_done); 3948722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct creg_completion completion; 3958722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned long timeout; 3968722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int st; 3978722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 3988722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com completion.cmd_done = &cmd_done; 3998722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com completion.st = 0; 4008722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com completion.creg_status = 0; 4018722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 4028722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com st = creg_queue_cmd(card, op, addr, cnt8, buf, stream, creg_cmd_done_cb, 4038722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com &completion); 4048722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (st) 4058722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return st; 4068722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 407c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher /* 408f37912039eb04979f269de0a7dc1a601702df51aPhilip J Kelleher * This timeout is necessary for unresponsive hardware. The additional 409c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher * 20 seconds to used to guarantee that each cregs requests has time to 410c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher * complete. 411c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher */ 412f37912039eb04979f269de0a7dc1a601702df51aPhilip J Kelleher timeout = msecs_to_jiffies(CREG_TIMEOUT_MSEC * 413f37912039eb04979f269de0a7dc1a601702df51aPhilip J Kelleher card->creg_ctrl.q_depth + 20000); 4148722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 4158722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com /* 4168722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * The creg interface is guaranteed to complete. It has a timeout 4178722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * mechanism that will kick in if hardware does not respond. 4188722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com */ 4198722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com st = wait_for_completion_timeout(completion.cmd_done, timeout); 4208722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (st == 0) { 4218722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com /* 4228722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * This is really bad, because the kernel timer did not 4238722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * expire and notify us of a timeout! 4248722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com */ 4258722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_crit(CARD_TO_DEV(card), 4268722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com "cregs timer failed\n"); 4278722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com creg_reset(card); 4288722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return -EIO; 4298722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 4308722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 4318722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com *hw_stat = completion.creg_status; 4328722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 4338722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (completion.st) { 434b8b225da139f5770d7689b189fd5debc58f4b35dPhilip J Kelleher /* 435b8b225da139f5770d7689b189fd5debc58f4b35dPhilip J Kelleher * This read is needed to verify that there has not been any 436b8b225da139f5770d7689b189fd5debc58f4b35dPhilip J Kelleher * extreme errors that might have occurred, i.e. EEH. The 437b8b225da139f5770d7689b189fd5debc58f4b35dPhilip J Kelleher * function iowrite32 will not detect EEH errors, so it is 438b8b225da139f5770d7689b189fd5debc58f4b35dPhilip J Kelleher * necessary that we recover if such an error is the reason 439b8b225da139f5770d7689b189fd5debc58f4b35dPhilip J Kelleher * for the timeout. This is a dummy read. 440b8b225da139f5770d7689b189fd5debc58f4b35dPhilip J Kelleher */ 441b8b225da139f5770d7689b189fd5debc58f4b35dPhilip J Kelleher ioread32(card->regmap + SCRATCH); 442b8b225da139f5770d7689b189fd5debc58f4b35dPhilip J Kelleher 4438722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_warn(CARD_TO_DEV(card), 4448722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com "creg command failed(%d x%08x)\n", 4458722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com completion.st, addr); 4468722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return completion.st; 4478722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 4488722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 4498722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return 0; 4508722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 4518722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 4528722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comstatic int issue_creg_rw(struct rsxx_cardinfo *card, 4538722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com u32 addr, 4548722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int size8, 4558722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com void *data, 4568722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int stream, 4578722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int read) 4588722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 4598722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int hw_stat; 4608722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int xfer; 4618722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int op; 4628722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int st; 4638722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 4648722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com op = read ? CREG_OP_READ : CREG_OP_WRITE; 4658722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 4668722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com do { 4678722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com xfer = min_t(unsigned int, size8, MAX_CREG_DATA8); 4688722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 4698722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com st = __issue_creg_rw(card, op, addr, xfer, 4708722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com data, stream, &hw_stat); 4718722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (st) 4728722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return st; 4738722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 474c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher data = (char *)data + xfer; 4758722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com addr += xfer; 4768722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com size8 -= xfer; 4778722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } while (size8); 4788722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 4798722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return 0; 4808722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 4818722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 4828722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com/* ---------------------------- Public API ---------------------------------- */ 4838722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comint rsxx_creg_write(struct rsxx_cardinfo *card, 4848722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com u32 addr, 4858722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int size8, 4868722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com void *data, 4878722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int byte_stream) 4888722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 4898722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return issue_creg_rw(card, addr, size8, data, byte_stream, 0); 4908722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 4918722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 4928722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comint rsxx_creg_read(struct rsxx_cardinfo *card, 4938722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com u32 addr, 4948722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int size8, 4958722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com void *data, 4968722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int byte_stream) 4978722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 4988722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return issue_creg_rw(card, addr, size8, data, byte_stream, 1); 4998722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 5008722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 5018722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comint rsxx_get_card_state(struct rsxx_cardinfo *card, unsigned int *state) 5028722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 5038722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return rsxx_creg_read(card, CREG_ADD_CARD_STATE, 5048722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com sizeof(*state), state, 0); 5058722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 5068722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 5078722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comint rsxx_get_card_size8(struct rsxx_cardinfo *card, u64 *size8) 5088722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 5098722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int size; 5108722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int st; 5118722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 5128722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com st = rsxx_creg_read(card, CREG_ADD_CARD_SIZE, 5138722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com sizeof(size), &size, 0); 5148722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (st) 5158722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return st; 5168722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 5178722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com *size8 = (u64)size * RSXX_HW_BLK_SIZE; 5188722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return 0; 5198722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 5208722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 5218722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comint rsxx_get_num_targets(struct rsxx_cardinfo *card, 5228722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int *n_targets) 5238722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 5248722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return rsxx_creg_read(card, CREG_ADD_NUM_TARGETS, 5258722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com sizeof(*n_targets), n_targets, 0); 5268722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 5278722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 5288722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comint rsxx_get_card_capabilities(struct rsxx_cardinfo *card, 5298722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com u32 *capabilities) 5308722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 5318722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return rsxx_creg_read(card, CREG_ADD_CAPABILITIES, 5328722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com sizeof(*capabilities), capabilities, 0); 5338722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 5348722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 5358722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comint rsxx_issue_card_cmd(struct rsxx_cardinfo *card, u32 cmd) 5368722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 5378722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return rsxx_creg_write(card, CREG_ADD_CARD_CMD, 5388722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com sizeof(cmd), &cmd, 0); 5398722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 5408722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 5418722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 5428722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com/*----------------- HW Log Functions -------------------*/ 5438722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comstatic void hw_log_msg(struct rsxx_cardinfo *card, const char *str, int len) 5448722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 5458722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com static char level; 5468722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 5478722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com /* 5488722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * New messages start with "<#>", where # is the log level. Messages 5498722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * that extend past the log buffer will use the previous level 5508722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com */ 5518722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if ((len > 3) && (str[0] == '<') && (str[2] == '>')) { 5528722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com level = str[1]; 5538722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com str += 3; /* Skip past the log level. */ 5548722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com len -= 3; 5558722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 5568722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 5578722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com switch (level) { 5588722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com case '0': 5598722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_emerg(CARD_TO_DEV(card), "HW: %.*s", len, str); 5608722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com break; 5618722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com case '1': 5628722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_alert(CARD_TO_DEV(card), "HW: %.*s", len, str); 5638722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com break; 5648722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com case '2': 5658722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_crit(CARD_TO_DEV(card), "HW: %.*s", len, str); 5668722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com break; 5678722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com case '3': 5688722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_err(CARD_TO_DEV(card), "HW: %.*s", len, str); 5698722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com break; 5708722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com case '4': 5718722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_warn(CARD_TO_DEV(card), "HW: %.*s", len, str); 5728722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com break; 5738722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com case '5': 5748722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_notice(CARD_TO_DEV(card), "HW: %.*s", len, str); 5758722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com break; 5768722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com case '6': 5778722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_info(CARD_TO_DEV(card), "HW: %.*s", len, str); 5788722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com break; 5798722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com case '7': 5808722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_dbg(CARD_TO_DEV(card), "HW: %.*s", len, str); 5818722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com break; 5828722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com default: 5838722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_info(CARD_TO_DEV(card), "HW: %.*s", len, str); 5848722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com break; 5858722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 5868722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 5878722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 5888722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com/* 589c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher * The substrncpy function copies the src string (which includes the 590c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher * terminating '\0' character), up to the count into the dest pointer. 591c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher * Returns the number of bytes copied to dest. 5928722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com */ 5938722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comstatic int substrncpy(char *dest, const char *src, int count) 5948722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 5958722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int max_cnt = count; 5968722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 5978722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com while (count) { 5988722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com count--; 5998722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com *dest = *src; 6008722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (*dest == '\0') 6018722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com break; 6028722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com src++; 6038722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dest++; 6048722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 6058722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return max_cnt - count; 6068722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 6078722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 6088722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 6098722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comstatic void read_hw_log_done(struct rsxx_cardinfo *card, 6108722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct creg_cmd *cmd, 6118722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int st) 6128722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 6138722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com char *buf; 6148722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com char *log_str; 6158722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int cnt; 6168722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int len; 6178722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int off; 6188722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 6198722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com buf = cmd->buf; 6208722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com off = 0; 6218722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 6228722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com /* Failed getting the log message */ 6238722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (st) 6248722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return; 6258722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 6268722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com while (off < cmd->cnt8) { 6278722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com log_str = &card->log.buf[card->log.buf_len]; 6288722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cnt = min(cmd->cnt8 - off, LOG_BUF_SIZE8 - card->log.buf_len); 6298722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com len = substrncpy(log_str, &buf[off], cnt); 6308722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 6318722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com off += len; 6328722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->log.buf_len += len; 6338722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 6348722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com /* 6358722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * Flush the log if we've hit the end of a message or if we've 6368722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com * run out of buffer space. 6378722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com */ 6388722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if ((log_str[len - 1] == '\0') || 6398722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com (card->log.buf_len == LOG_BUF_SIZE8)) { 6408722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (card->log.buf_len != 1) /* Don't log blank lines. */ 6418722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com hw_log_msg(card, card->log.buf, 6428722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->log.buf_len); 6438722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->log.buf_len = 0; 6448722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 6458722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 6468722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 6478722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 6488722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (cmd->status & CREG_STAT_LOG_PENDING) 6498722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com rsxx_read_hw_log(card); 6508722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 6518722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 6528722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comint rsxx_read_hw_log(struct rsxx_cardinfo *card) 6538722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 6548722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int st; 6558722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 6568722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com st = creg_queue_cmd(card, CREG_OP_READ, CREG_ADD_LOG, 6578722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com sizeof(card->log.tmp), card->log.tmp, 6588722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 1, read_hw_log_done, NULL); 6598722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (st) 6608722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_err(CARD_TO_DEV(card), 6618722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com "Failed getting log text\n"); 6628722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 6638722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return st; 6648722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 6658722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 6668722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com/*-------------- IOCTL REG Access ------------------*/ 6678722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comstatic int issue_reg_cmd(struct rsxx_cardinfo *card, 6688722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct rsxx_reg_access *cmd, 6698722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int read) 6708722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 6718722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com unsigned int op = read ? CREG_OP_READ : CREG_OP_WRITE; 6728722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 6738722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return __issue_creg_rw(card, op, cmd->addr, cmd->cnt, cmd->data, 6748722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd->stream, &cmd->stat); 6758722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 6768722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 6778722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comint rsxx_reg_access(struct rsxx_cardinfo *card, 6788722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct rsxx_reg_access __user *ucmd, 6798722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int read) 6808722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 6818722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct rsxx_reg_access cmd; 6828722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int st; 6838722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 6848722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com st = copy_from_user(&cmd, ucmd, sizeof(cmd)); 6858722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (st) 6868722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return -EFAULT; 6878722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 688c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher if (cmd.cnt > RSXX_MAX_REG_CNT) 689c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher return -EFAULT; 690c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher 6918722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com st = issue_reg_cmd(card, &cmd, read); 6928722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (st) 6938722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return st; 6948722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 6958722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com st = put_user(cmd.stat, &ucmd->stat); 6968722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (st) 6978722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return -EFAULT; 6988722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 6998722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (read) { 7008722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com st = copy_to_user(ucmd->data, cmd.data, cmd.cnt); 7018722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (st) 7028722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return -EFAULT; 7038722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 7048722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 7058722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return 0; 7068722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 7078722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 708c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kellehervoid rsxx_eeh_save_issued_creg(struct rsxx_cardinfo *card) 709c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher{ 710c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher struct creg_cmd *cmd = NULL; 711c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher 712c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher cmd = card->creg_ctrl.active_cmd; 713c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher card->creg_ctrl.active_cmd = NULL; 714c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher 715c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher if (cmd) { 716c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher del_timer_sync(&card->creg_ctrl.cmd_timer); 717c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher 718c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher spin_lock_bh(&card->creg_ctrl.lock); 719c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher list_add(&cmd->list, &card->creg_ctrl.queue); 720c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher card->creg_ctrl.q_depth++; 721c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher card->creg_ctrl.active = 0; 722c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher spin_unlock_bh(&card->creg_ctrl.lock); 723c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher } 724c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher} 725c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher 726c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kellehervoid rsxx_kick_creg_queue(struct rsxx_cardinfo *card) 727c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher{ 728c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher spin_lock_bh(&card->creg_ctrl.lock); 729c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher if (!list_empty(&card->creg_ctrl.queue)) 730c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher creg_kick_queue(card); 731c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher spin_unlock_bh(&card->creg_ctrl.lock); 732c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher} 733c95246c3a2ac796cfa43e76200ede59cb4a1644fPhilip J Kelleher 7348722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com/*------------ Initialization & Setup --------------*/ 7358722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comint rsxx_creg_setup(struct rsxx_cardinfo *card) 7368722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 7378722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->creg_ctrl.active_cmd = NULL; 7388722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 739a3299ab18591d36ad5622f5064619123c439b779Philip J Kelleher card->creg_ctrl.creg_wq = 740a3299ab18591d36ad5622f5064619123c439b779Philip J Kelleher create_singlethread_workqueue(DRIVER_NAME"_creg"); 741a3299ab18591d36ad5622f5064619123c439b779Philip J Kelleher if (!card->creg_ctrl.creg_wq) 742a3299ab18591d36ad5622f5064619123c439b779Philip J Kelleher return -ENOMEM; 743a3299ab18591d36ad5622f5064619123c439b779Philip J Kelleher 7448722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com INIT_WORK(&card->creg_ctrl.done_work, creg_cmd_done); 7458722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com mutex_init(&card->creg_ctrl.reset_lock); 7468722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com INIT_LIST_HEAD(&card->creg_ctrl.queue); 747c206c70924737db6836382c09ad2dacd04bb6204Philip J Kelleher spin_lock_init(&card->creg_ctrl.lock); 7488722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com setup_timer(&card->creg_ctrl.cmd_timer, creg_cmd_timed_out, 7498722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com (unsigned long) card); 7508722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 7518722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return 0; 7528722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 7538722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 7548722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comvoid rsxx_creg_destroy(struct rsxx_cardinfo *card) 7558722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 7568722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct creg_cmd *cmd; 7578722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com struct creg_cmd *tmp; 7588722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com int cnt = 0; 7598722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 7608722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com /* Cancel outstanding commands */ 76103ac03a8971bd7e9f8c8b20a309b61beaf154d60Philip J Kelleher spin_lock_bh(&card->creg_ctrl.lock); 7628722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) { 7638722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com list_del(&cmd->list); 7648722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (cmd->cb) 7658722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd->cb(card, cmd, -ECANCELED); 7668722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com kmem_cache_free(creg_cmd_pool, cmd); 7678722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cnt++; 7688722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 7698722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 7708722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (cnt) 7718722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_info(CARD_TO_DEV(card), 7728722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com "Canceled %d queue creg commands\n", cnt); 7738722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 7748722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd = card->creg_ctrl.active_cmd; 7758722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com card->creg_ctrl.active_cmd = NULL; 7768722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (cmd) { 7778722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (timer_pending(&card->creg_ctrl.cmd_timer)) 7788722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com del_timer_sync(&card->creg_ctrl.cmd_timer); 7798722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 7808722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (cmd->cb) 7818722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cmd->cb(card, cmd, -ECANCELED); 7828722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com dev_info(CARD_TO_DEV(card), 7838722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com "Canceled active creg command\n"); 7848722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com kmem_cache_free(creg_cmd_pool, cmd); 7858722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com } 78603ac03a8971bd7e9f8c8b20a309b61beaf154d60Philip J Kelleher spin_unlock_bh(&card->creg_ctrl.lock); 7878722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 7888722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com cancel_work_sync(&card->creg_ctrl.done_work); 7898722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 7908722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 7918722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 7928722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comint rsxx_creg_init(void) 7938722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 7948722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com creg_cmd_pool = KMEM_CACHE(creg_cmd, SLAB_HWCACHE_ALIGN); 7958722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com if (!creg_cmd_pool) 7968722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return -ENOMEM; 7978722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 7988722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com return 0; 7998722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 8008722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com 8018722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.comvoid rsxx_creg_cleanup(void) 8028722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com{ 8038722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com kmem_cache_destroy(creg_cmd_pool); 8048722ff8cdbfac9c1b20e67bb067b455c48cb8e93josh.h.morris@us.ibm.com} 805