Commit 8328258e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc:
  sdhci: release irq during suspend
  sdhci: make isr tolerant of read errors
  mmc: require explicit support for high-speed
  ncpfs: make sure server connection survives a kill
parents 205c911d a715dfc7
...@@ -376,10 +376,11 @@ static inline void mmc_set_ios(struct mmc_host *host) ...@@ -376,10 +376,11 @@ static inline void mmc_set_ios(struct mmc_host *host)
{ {
struct mmc_ios *ios = &host->ios; struct mmc_ios *ios = &host->ios;
pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n", pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u "
"width %u timing %u\n",
mmc_hostname(host), ios->clock, ios->bus_mode, mmc_hostname(host), ios->clock, ios->bus_mode,
ios->power_mode, ios->chip_select, ios->vdd, ios->power_mode, ios->chip_select, ios->vdd,
ios->bus_width); ios->bus_width, ios->timing);
host->ops->set_ios(host, ios); host->ops->set_ios(host, ios);
} }
...@@ -809,6 +810,7 @@ static void mmc_power_up(struct mmc_host *host) ...@@ -809,6 +810,7 @@ static void mmc_power_up(struct mmc_host *host)
host->ios.chip_select = MMC_CS_DONTCARE; host->ios.chip_select = MMC_CS_DONTCARE;
host->ios.power_mode = MMC_POWER_UP; host->ios.power_mode = MMC_POWER_UP;
host->ios.bus_width = MMC_BUS_WIDTH_1; host->ios.bus_width = MMC_BUS_WIDTH_1;
host->ios.timing = MMC_TIMING_LEGACY;
mmc_set_ios(host); mmc_set_ios(host);
mmc_delay(1); mmc_delay(1);
...@@ -828,6 +830,7 @@ static void mmc_power_off(struct mmc_host *host) ...@@ -828,6 +830,7 @@ static void mmc_power_off(struct mmc_host *host)
host->ios.chip_select = MMC_CS_DONTCARE; host->ios.chip_select = MMC_CS_DONTCARE;
host->ios.power_mode = MMC_POWER_OFF; host->ios.power_mode = MMC_POWER_OFF;
host->ios.bus_width = MMC_BUS_WIDTH_1; host->ios.bus_width = MMC_BUS_WIDTH_1;
host->ios.timing = MMC_TIMING_LEGACY;
mmc_set_ios(host); mmc_set_ios(host);
} }
...@@ -1112,6 +1115,7 @@ static void mmc_process_ext_csds(struct mmc_host *host) ...@@ -1112,6 +1115,7 @@ static void mmc_process_ext_csds(struct mmc_host *host)
continue; continue;
} }
if (host->caps & MMC_CAP_MMC_HIGHSPEED) {
/* Activate highspeed support. */ /* Activate highspeed support. */
cmd.opcode = MMC_SWITCH; cmd.opcode = MMC_SWITCH;
cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
...@@ -1130,11 +1134,12 @@ static void mmc_process_ext_csds(struct mmc_host *host) ...@@ -1130,11 +1134,12 @@ static void mmc_process_ext_csds(struct mmc_host *host)
mmc_card_set_highspeed(card); mmc_card_set_highspeed(card);
/* Check for host support for wide-bus modes. */ host->ios.timing = MMC_TIMING_SD_HS;
if (!(host->caps & MMC_CAP_4_BIT_DATA)) { mmc_set_ios(host);
continue;
} }
/* Check for host support for wide-bus modes. */
if (host->caps & MMC_CAP_4_BIT_DATA) {
/* Activate 4-bit support. */ /* Activate 4-bit support. */
cmd.opcode = MMC_SWITCH; cmd.opcode = MMC_SWITCH;
cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
...@@ -1152,6 +1157,8 @@ static void mmc_process_ext_csds(struct mmc_host *host) ...@@ -1152,6 +1157,8 @@ static void mmc_process_ext_csds(struct mmc_host *host)
} }
host->ios.bus_width = MMC_BUS_WIDTH_4; host->ios.bus_width = MMC_BUS_WIDTH_4;
mmc_set_ios(host);
}
} }
kfree(ext_csd); kfree(ext_csd);
...@@ -1241,6 +1248,9 @@ static void mmc_read_switch_caps(struct mmc_host *host) ...@@ -1241,6 +1248,9 @@ static void mmc_read_switch_caps(struct mmc_host *host)
unsigned char *status; unsigned char *status;
struct scatterlist sg; struct scatterlist sg;
if (!(host->caps & MMC_CAP_SD_HIGHSPEED))
return;
status = kmalloc(64, GFP_KERNEL); status = kmalloc(64, GFP_KERNEL);
if (!status) { if (!status) {
printk(KERN_WARNING "%s: Unable to allocate buffer for " printk(KERN_WARNING "%s: Unable to allocate buffer for "
...@@ -1332,6 +1342,9 @@ static void mmc_read_switch_caps(struct mmc_host *host) ...@@ -1332,6 +1342,9 @@ static void mmc_read_switch_caps(struct mmc_host *host)
} }
mmc_card_set_highspeed(card); mmc_card_set_highspeed(card);
host->ios.timing = MMC_TIMING_SD_HS;
mmc_set_ios(host);
} }
kfree(status); kfree(status);
......
...@@ -606,7 +606,6 @@ static void sdhci_finish_command(struct sdhci_host *host) ...@@ -606,7 +606,6 @@ static void sdhci_finish_command(struct sdhci_host *host)
static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
{ {
int div; int div;
u8 ctrl;
u16 clk; u16 clk;
unsigned long timeout; unsigned long timeout;
...@@ -615,13 +614,6 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) ...@@ -615,13 +614,6 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
if (clock > 25000000)
ctrl |= SDHCI_CTRL_HISPD;
else
ctrl &= ~SDHCI_CTRL_HISPD;
writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
if (clock == 0) if (clock == 0)
goto out; goto out;
...@@ -761,10 +753,17 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -761,10 +753,17 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
sdhci_set_power(host, ios->vdd); sdhci_set_power(host, ios->vdd);
ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
if (ios->bus_width == MMC_BUS_WIDTH_4) if (ios->bus_width == MMC_BUS_WIDTH_4)
ctrl |= SDHCI_CTRL_4BITBUS; ctrl |= SDHCI_CTRL_4BITBUS;
else else
ctrl &= ~SDHCI_CTRL_4BITBUS; ctrl &= ~SDHCI_CTRL_4BITBUS;
if (ios->timing == MMC_TIMING_SD_HS)
ctrl |= SDHCI_CTRL_HISPD;
else
ctrl &= ~SDHCI_CTRL_HISPD;
writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
mmiowb(); mmiowb();
...@@ -994,7 +993,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) ...@@ -994,7 +993,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
intmask = readl(host->ioaddr + SDHCI_INT_STATUS); intmask = readl(host->ioaddr + SDHCI_INT_STATUS);
if (!intmask) { if (!intmask || intmask == 0xffffffff) {
result = IRQ_NONE; result = IRQ_NONE;
goto out; goto out;
} }
...@@ -1080,6 +1079,13 @@ static int sdhci_suspend (struct pci_dev *pdev, pm_message_t state) ...@@ -1080,6 +1079,13 @@ static int sdhci_suspend (struct pci_dev *pdev, pm_message_t state)
pci_save_state(pdev); pci_save_state(pdev);
pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
for (i = 0;i < chip->num_slots;i++) {
if (!chip->hosts[i])
continue;
free_irq(chip->hosts[i]->irq, chip->hosts[i]);
}
pci_disable_device(pdev); pci_disable_device(pdev);
pci_set_power_state(pdev, pci_choose_state(pdev, state)); pci_set_power_state(pdev, pci_choose_state(pdev, state));
...@@ -1108,6 +1114,11 @@ static int sdhci_resume (struct pci_dev *pdev) ...@@ -1108,6 +1114,11 @@ static int sdhci_resume (struct pci_dev *pdev)
continue; continue;
if (chip->hosts[i]->flags & SDHCI_USE_DMA) if (chip->hosts[i]->flags & SDHCI_USE_DMA)
pci_set_master(pdev); pci_set_master(pdev);
ret = request_irq(chip->hosts[i]->irq, sdhci_irq,
IRQF_SHARED, chip->hosts[i]->slot_descr,
chip->hosts[i]);
if (ret)
return ret;
sdhci_init(chip->hosts[i]); sdhci_init(chip->hosts[i]);
mmiowb(); mmiowb();
ret = mmc_resume_host(chip->hosts[i]->mmc); ret = mmc_resume_host(chip->hosts[i]->mmc);
...@@ -1274,6 +1285,9 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) ...@@ -1274,6 +1285,9 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
mmc->f_max = host->max_clk; mmc->f_max = host->max_clk;
mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK; mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
if (caps & SDHCI_CAN_DO_HISPD)
mmc->caps |= MMC_CAP_SD_HIGHSPEED;
mmc->ocr_avail = 0; mmc->ocr_avail = 0;
if (caps & SDHCI_CAN_VDD_330) if (caps & SDHCI_CAN_VDD_330)
mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34; mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
...@@ -1282,13 +1296,6 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) ...@@ -1282,13 +1296,6 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
if (caps & SDHCI_CAN_VDD_180) if (caps & SDHCI_CAN_VDD_180)
mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19; mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19;
if ((host->max_clk > 25000000) && !(caps & SDHCI_CAN_DO_HISPD)) {
printk(KERN_ERR "%s: Controller reports > 25 MHz base clock,"
" but no high speed support.\n",
host->slot_descr);
mmc->f_max = 25000000;
}
if (mmc->ocr_avail == 0) { if (mmc->ocr_avail == 0) {
printk(KERN_ERR "%s: Hardware doesn't report any " printk(KERN_ERR "%s: Hardware doesn't report any "
"support voltages.\n", host->slot_descr); "support voltages.\n", host->slot_descr);
......
...@@ -576,6 +576,12 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) ...@@ -576,6 +576,12 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
server->packet = vmalloc(NCP_PACKET_SIZE); server->packet = vmalloc(NCP_PACKET_SIZE);
if (server->packet == NULL) if (server->packet == NULL)
goto out_nls; goto out_nls;
server->txbuf = vmalloc(NCP_PACKET_SIZE);
if (server->txbuf == NULL)
goto out_packet;
server->rxbuf = vmalloc(NCP_PACKET_SIZE);
if (server->rxbuf == NULL)
goto out_txbuf;
sock->sk->sk_data_ready = ncp_tcp_data_ready; sock->sk->sk_data_ready = ncp_tcp_data_ready;
sock->sk->sk_error_report = ncp_tcp_error_report; sock->sk->sk_error_report = ncp_tcp_error_report;
...@@ -597,7 +603,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) ...@@ -597,7 +603,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
error = ncp_connect(server); error = ncp_connect(server);
ncp_unlock_server(server); ncp_unlock_server(server);
if (error < 0) if (error < 0)
goto out_packet; goto out_rxbuf;
DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb)); DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */ error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */
...@@ -666,8 +672,12 @@ out_disconnect: ...@@ -666,8 +672,12 @@ out_disconnect:
ncp_lock_server(server); ncp_lock_server(server);
ncp_disconnect(server); ncp_disconnect(server);
ncp_unlock_server(server); ncp_unlock_server(server);
out_packet: out_rxbuf:
ncp_stop_tasks(server); ncp_stop_tasks(server);
vfree(server->rxbuf);
out_txbuf:
vfree(server->txbuf);
out_packet:
vfree(server->packet); vfree(server->packet);
out_nls: out_nls:
#ifdef CONFIG_NCPFS_NLS #ifdef CONFIG_NCPFS_NLS
...@@ -723,6 +733,8 @@ static void ncp_put_super(struct super_block *sb) ...@@ -723,6 +733,8 @@ static void ncp_put_super(struct super_block *sb)
kfree(server->priv.data); kfree(server->priv.data);
kfree(server->auth.object_name); kfree(server->auth.object_name);
vfree(server->rxbuf);
vfree(server->txbuf);
vfree(server->packet); vfree(server->packet);
sb->s_fs_info = NULL; sb->s_fs_info = NULL;
kfree(server); kfree(server);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/string.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/in.h> #include <linux/in.h>
#include <linux/net.h> #include <linux/net.h>
...@@ -55,10 +56,11 @@ static int _send(struct socket *sock, const void *buff, int len) ...@@ -55,10 +56,11 @@ static int _send(struct socket *sock, const void *buff, int len)
struct ncp_request_reply { struct ncp_request_reply {
struct list_head req; struct list_head req;
wait_queue_head_t wq; wait_queue_head_t wq;
struct ncp_reply_header* reply_buf; atomic_t refs;
unsigned char* reply_buf;
size_t datalen; size_t datalen;
int result; int result;
enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE } status; enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE, RQ_ABANDONED } status;
struct kvec* tx_ciov; struct kvec* tx_ciov;
size_t tx_totallen; size_t tx_totallen;
size_t tx_iovlen; size_t tx_iovlen;
...@@ -67,6 +69,32 @@ struct ncp_request_reply { ...@@ -67,6 +69,32 @@ struct ncp_request_reply {
u_int32_t sign[6]; u_int32_t sign[6];
}; };
static inline struct ncp_request_reply* ncp_alloc_req(void)
{
struct ncp_request_reply *req;
req = kmalloc(sizeof(struct ncp_request_reply), GFP_KERNEL);
if (!req)
return NULL;
init_waitqueue_head(&req->wq);
atomic_set(&req->refs, (1));
req->status = RQ_IDLE;
return req;
}
static void ncp_req_get(struct ncp_request_reply *req)
{
atomic_inc(&req->refs);
}
static void ncp_req_put(struct ncp_request_reply *req)
{
if (atomic_dec_and_test(&req->refs))
kfree(req);
}
void ncp_tcp_data_ready(struct sock *sk, int len) void ncp_tcp_data_ready(struct sock *sk, int len)
{ {
struct ncp_server *server = sk->sk_user_data; struct ncp_server *server = sk->sk_user_data;
...@@ -101,14 +129,17 @@ void ncpdgram_timeout_call(unsigned long v) ...@@ -101,14 +129,17 @@ void ncpdgram_timeout_call(unsigned long v)
schedule_work(&server->timeout_tq); schedule_work(&server->timeout_tq);
} }
static inline void ncp_finish_request(struct ncp_request_reply *req, int result) static inline void ncp_finish_request(struct ncp_server *server, struct ncp_request_reply *req, int result)
{ {
req->result = result; req->result = result;
if (req->status != RQ_ABANDONED)
memcpy(req->reply_buf, server->rxbuf, req->datalen);
req->status = RQ_DONE; req->status = RQ_DONE;
wake_up_all(&req->wq); wake_up_all(&req->wq);
ncp_req_put(req);
} }
static void __abort_ncp_connection(struct ncp_server *server, struct ncp_request_reply *aborted, int err) static void __abort_ncp_connection(struct ncp_server *server)
{ {
struct ncp_request_reply *req; struct ncp_request_reply *req;
...@@ -118,31 +149,19 @@ static void __abort_ncp_connection(struct ncp_server *server, struct ncp_request ...@@ -118,31 +149,19 @@ static void __abort_ncp_connection(struct ncp_server *server, struct ncp_request
req = list_entry(server->tx.requests.next, struct ncp_request_reply, req); req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
list_del_init(&req->req); list_del_init(&req->req);
if (req == aborted) { ncp_finish_request(server, req, -EIO);
ncp_finish_request(req, err);
} else {
ncp_finish_request(req, -EIO);
}
} }
req = server->rcv.creq; req = server->rcv.creq;
if (req) { if (req) {
server->rcv.creq = NULL; server->rcv.creq = NULL;
if (req == aborted) { ncp_finish_request(server, req, -EIO);
ncp_finish_request(req, err);
} else {
ncp_finish_request(req, -EIO);
}
server->rcv.ptr = NULL; server->rcv.ptr = NULL;
server->rcv.state = 0; server->rcv.state = 0;
} }
req = server->tx.creq; req = server->tx.creq;
if (req) { if (req) {
server->tx.creq = NULL; server->tx.creq = NULL;
if (req == aborted) { ncp_finish_request(server, req, -EIO);
ncp_finish_request(req, err);
} else {
ncp_finish_request(req, -EIO);
}
} }
} }
...@@ -160,10 +179,12 @@ static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_req ...@@ -160,10 +179,12 @@ static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_req
break; break;
case RQ_QUEUED: case RQ_QUEUED:
list_del_init(&req->req); list_del_init(&req->req);
ncp_finish_request(req, err); ncp_finish_request(server, req, err);
break; break;
case RQ_INPROGRESS: case RQ_INPROGRESS:
__abort_ncp_connection(server, req, err); req->status = RQ_ABANDONED;
break;
case RQ_ABANDONED:
break; break;
} }
} }
...@@ -177,7 +198,7 @@ static inline void ncp_abort_request(struct ncp_server *server, struct ncp_reque ...@@ -177,7 +198,7 @@ static inline void ncp_abort_request(struct ncp_server *server, struct ncp_reque
static inline void __ncptcp_abort(struct ncp_server *server) static inline void __ncptcp_abort(struct ncp_server *server)
{ {
__abort_ncp_connection(server, NULL, 0); __abort_ncp_connection(server);
} }
static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req) static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req)
...@@ -294,6 +315,11 @@ static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_r ...@@ -294,6 +315,11 @@ static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_r
static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req) static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req)
{ {
/* we copy the data so that we do not depend on the caller
staying alive */
memcpy(server->txbuf, req->tx_iov[1].iov_base, req->tx_iov[1].iov_len);
req->tx_iov[1].iov_base = server->txbuf;
if (server->ncp_sock->type == SOCK_STREAM) if (server->ncp_sock->type == SOCK_STREAM)
ncptcp_start_request(server, req); ncptcp_start_request(server, req);
else else
...@@ -308,6 +334,7 @@ static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply * ...@@ -308,6 +334,7 @@ static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply *
printk(KERN_ERR "ncpfs: tcp: Server died\n"); printk(KERN_ERR "ncpfs: tcp: Server died\n");
return -EIO; return -EIO;
} }
ncp_req_get(req);
if (server->tx.creq || server->rcv.creq) { if (server->tx.creq || server->rcv.creq) {
req->status = RQ_QUEUED; req->status = RQ_QUEUED;
list_add_tail(&req->req, &server->tx.requests); list_add_tail(&req->req, &server->tx.requests);
...@@ -409,7 +436,7 @@ void ncpdgram_rcv_proc(struct work_struct *work) ...@@ -409,7 +436,7 @@ void ncpdgram_rcv_proc(struct work_struct *work)
server->timeout_last = NCP_MAX_RPC_TIMEOUT; server->timeout_last = NCP_MAX_RPC_TIMEOUT;
mod_timer(&server->timeout_tm, jiffies + NCP_MAX_RPC_TIMEOUT); mod_timer(&server->timeout_tm, jiffies + NCP_MAX_RPC_TIMEOUT);
} else if (reply.type == NCP_REPLY) { } else if (reply.type == NCP_REPLY) {
result = _recv(sock, (void*)req->reply_buf, req->datalen, MSG_DONTWAIT); result = _recv(sock, server->rxbuf, req->datalen, MSG_DONTWAIT);
#ifdef CONFIG_NCPFS_PACKET_SIGNING #ifdef CONFIG_NCPFS_PACKET_SIGNING
if (result >= 0 && server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) { if (result >= 0 && server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
if (result < 8 + 8) { if (result < 8 + 8) {
...@@ -419,7 +446,7 @@ void ncpdgram_rcv_proc(struct work_struct *work) ...@@ -419,7 +446,7 @@ void ncpdgram_rcv_proc(struct work_struct *work)
result -= 8; result -= 8;
hdrl = sock->sk->sk_family == AF_INET ? 8 : 6; hdrl = sock->sk->sk_family == AF_INET ? 8 : 6;
if (sign_verify_reply(server, ((char*)req->reply_buf) + hdrl, result - hdrl, cpu_to_le32(result), ((char*)req->reply_buf) + result)) { if (sign_verify_reply(server, server->rxbuf + hdrl, result - hdrl, cpu_to_le32(result), server->rxbuf + result)) {
printk(KERN_INFO "ncpfs: Signature violation\n"); printk(KERN_INFO "ncpfs: Signature violation\n");
result = -EIO; result = -EIO;
} }
...@@ -428,7 +455,7 @@ void ncpdgram_rcv_proc(struct work_struct *work) ...@@ -428,7 +455,7 @@ void ncpdgram_rcv_proc(struct work_struct *work)
#endif #endif
del_timer(&server->timeout_tm); del_timer(&server->timeout_tm);
server->rcv.creq = NULL; server->rcv.creq = NULL;
ncp_finish_request(req, result); ncp_finish_request(server, req, result);
__ncp_next_request(server); __ncp_next_request(server);
mutex_unlock(&server->rcv.creq_mutex); mutex_unlock(&server->rcv.creq_mutex);
continue; continue;
...@@ -478,12 +505,6 @@ void ncpdgram_timeout_proc(struct work_struct *work) ...@@ -478,12 +505,6 @@ void ncpdgram_timeout_proc(struct work_struct *work)
mutex_unlock(&server->rcv.creq_mutex); mutex_unlock(&server->rcv.creq_mutex);
} }
static inline void ncp_init_req(struct ncp_request_reply* req)
{
init_waitqueue_head(&req->wq);
req->status = RQ_IDLE;
}
static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len) static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len)
{ {
int result; int result;
...@@ -601,8 +622,8 @@ skipdata:; ...@@ -601,8 +622,8 @@ skipdata:;
goto skipdata; goto skipdata;
} }
req->datalen = datalen - 8; req->datalen = datalen - 8;
req->reply_buf->type = NCP_REPLY; ((struct ncp_reply_header*)server->rxbuf)->type = NCP_REPLY;
server->rcv.ptr = (unsigned char*)(req->reply_buf) + 2; server->rcv.ptr = server->rxbuf + 2;
server->rcv.len = datalen - 10; server->rcv.len = datalen - 10;
server->rcv.state = 1; server->rcv.state = 1;
break; break;
...@@ -615,12 +636,12 @@ skipdata:; ...@@ -615,12 +636,12 @@ skipdata:;
case 1: case 1:
req = server->rcv.creq; req = server->rcv.creq;
if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) { if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) {
if (req->reply_buf->sequence != server->sequence) { if (((struct ncp_reply_header*)server->rxbuf)->sequence != server->sequence) {
printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n"); printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n");
__ncp_abort_request(server, req, -EIO); __ncp_abort_request(server, req, -EIO);
return -EIO; return -EIO;
} }
if ((req->reply_buf->conn_low | (req->reply_buf->conn_high << 8)) != server->connection) { if ((((struct ncp_reply_header*)server->rxbuf)->conn_low | (((struct ncp_reply_header*)server->rxbuf)->conn_high << 8)) != server->connection) {
printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n"); printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n");
__ncp_abort_request(server, req, -EIO); __ncp_abort_request(server, req, -EIO);
return -EIO; return -EIO;
...@@ -628,14 +649,14 @@ skipdata:; ...@@ -628,14 +649,14 @@ skipdata:;
} }
#ifdef CONFIG_NCPFS_PACKET_SIGNING #ifdef CONFIG_NCPFS_PACKET_SIGNING
if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) { if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
if (sign_verify_reply(server, (unsigned char*)(req->reply_buf) + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) { if (sign_verify_reply(server, server->rxbuf + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) {
printk(KERN_ERR "ncpfs: tcp: Signature violation\n"); printk(KERN_ERR "ncpfs: tcp: Signature violation\n");
__ncp_abort_request(server, req, -EIO); __ncp_abort_request(server, req, -EIO);
return -EIO; return -EIO;
} }
} }
#endif #endif
ncp_finish_request(req, req->datalen); ncp_finish_request(server, req, req->datalen);
nextreq:; nextreq:;
__ncp_next_request(server); __ncp_next_request(server);
case 2: case 2:
...@@ -645,7 +666,7 @@ skipdata:; ...@@ -645,7 +666,7 @@ skipdata:;
server->rcv.state = 0; server->rcv.state = 0;
break; break;
case 3: case 3:
ncp_finish_request(server->rcv.creq, -EIO); ncp_finish_request(server, server->rcv.creq, -EIO);
goto nextreq; goto nextreq;
case 5: case 5:
info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len); info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len);
...@@ -675,28 +696,39 @@ void ncp_tcp_tx_proc(struct work_struct *work) ...@@ -675,28 +696,39 @@ void ncp_tcp_tx_proc(struct work_struct *work)
} }
static int do_ncp_rpc_call(struct ncp_server *server, int size, static int do_ncp_rpc_call(struct ncp_server *server, int size,
struct ncp_reply_header* reply_buf, int max_reply_size) unsigned char* reply_buf, int max_reply_size)
{ {
int result; int result;
struct ncp_request_reply req; struct ncp_request_reply *req;
ncp_init_req(&req); req = ncp_alloc_req();
req.reply_buf = reply_buf; if (!req)
req.datalen = max_reply_size; return -ENOMEM;
req.tx_iov[1].iov_base = server->packet;
req.tx_iov[1].iov_len = size; req->reply_buf = reply_buf;
req.tx_iovlen = 1; req->datalen = max_reply_size;
req.tx_totallen = size; req->tx_iov[1].iov_base = server->packet;
req.tx_type = *(u_int16_t*)server->packet; req->tx_iov[1].iov_len = size;
req->tx_iovlen = 1;
result = ncp_add_request(server, &req); req->tx_totallen = size;
if (result < 0) { req->tx_type = *(u_int16_t*)server->packet;
return result;
} result = ncp_add_request(server, req);
if (wait_event_interruptible(req.wq, req.status == RQ_DONE)) { if (result < 0)
ncp_abort_request(server, &req, -EIO); goto out;
if (wait_event_interruptible(req->wq, req->status == RQ_DONE)) {
ncp_abort_request(server, req, -EINTR);
result = -EINTR;
goto out;
} }
return req.result;
result = req->result;
out:
ncp_req_put(req);
return result;
} }
/* /*
...@@ -751,11 +783,6 @@ static int ncp_do_request(struct ncp_server *server, int size, ...@@ -751,11 +783,6 @@ static int ncp_do_request(struct ncp_server *server, int size,
DDPRINTK("do_ncp_rpc_call returned %d\n", result); DDPRINTK("do_ncp_rpc_call returned %d\n", result);
if (result < 0) {
/* There was a problem with I/O, so the connections is
* no longer usable. */
ncp_invalidate_conn(server);
}
return result; return result;
} }
......
...@@ -62,6 +62,12 @@ struct mmc_ios { ...@@ -62,6 +62,12 @@ struct mmc_ios {
#define MMC_BUS_WIDTH_1 0 #define MMC_BUS_WIDTH_1 0
#define MMC_BUS_WIDTH_4 2 #define MMC_BUS_WIDTH_4 2
unsigned char timing; /* timing specification used */
#define MMC_TIMING_LEGACY 0
#define MMC_TIMING_MMC_HS 1
#define MMC_TIMING_SD_HS 2
}; };
struct mmc_host_ops { struct mmc_host_ops {
...@@ -87,6 +93,8 @@ struct mmc_host { ...@@ -87,6 +93,8 @@ struct mmc_host {
#define MMC_CAP_4_BIT_DATA (1 << 0) /* Can the host do 4 bit transfers */ #define MMC_CAP_4_BIT_DATA (1 << 0) /* Can the host do 4 bit transfers */
#define MMC_CAP_MULTIWRITE (1 << 1) /* Can accurately report bytes sent to card on error */ #define MMC_CAP_MULTIWRITE (1 << 1) /* Can accurately report bytes sent to card on error */
#define MMC_CAP_BYTEBLOCK (1 << 2) /* Can do non-log2 block sizes */ #define MMC_CAP_BYTEBLOCK (1 << 2) /* Can do non-log2 block sizes */
#define MMC_CAP_MMC_HIGHSPEED (1 << 3) /* Can do MMC high-speed timing */
#define MMC_CAP_SD_HIGHSPEED (1 << 4) /* Can do SD high-speed timing */
/* host specific block data */ /* host specific block data */
unsigned int max_seg_size; /* see blk_queue_max_segment_size */ unsigned int max_seg_size; /* see blk_queue_max_segment_size */
......
...@@ -50,6 +50,8 @@ struct ncp_server { ...@@ -50,6 +50,8 @@ struct ncp_server {
int packet_size; int packet_size;
unsigned char *packet; /* Here we prepare requests and unsigned char *packet; /* Here we prepare requests and
receive replies */ receive replies */
unsigned char *txbuf; /* Storage for current request */
unsigned char *rxbuf; /* Storage for reply to current request */
int lock; /* To prevent mismatch in protocols. */ int lock; /* To prevent mismatch in protocols. */
struct mutex mutex; struct mutex mutex;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment