Commit ce1fedaa authored by David Hinds's avatar David Hinds Committed by Linus Torvalds

[PATCH] Small PCMCIA patch

Someone adding tests for failed kmalloc's (which is fine in itself)
did so in a way that would leave some PCMCIA data structures in
inconsistent states... and also introduced a fatal bug affecting
PCMCIA memory cards even when there are no kmalloc failures.
parent 2a4a59c1
...@@ -211,7 +211,7 @@ static void handle_erase_timeout(u_long arg) ...@@ -211,7 +211,7 @@ static void handle_erase_timeout(u_long arg)
retry_erase((erase_busy_t *)arg, MTD_REQ_TIMEOUT); retry_erase((erase_busy_t *)arg, MTD_REQ_TIMEOUT);
} }
static int setup_erase_request(client_handle_t handle, eraseq_entry_t *erase) static void setup_erase_request(client_handle_t handle, eraseq_entry_t *erase)
{ {
erase_busy_t *busy; erase_busy_t *busy;
region_info_t *info; region_info_t *info;
...@@ -229,8 +229,10 @@ static int setup_erase_request(client_handle_t handle, eraseq_entry_t *erase) ...@@ -229,8 +229,10 @@ static int setup_erase_request(client_handle_t handle, eraseq_entry_t *erase)
else { else {
erase->State = 1; erase->State = 1;
busy = kmalloc(sizeof(erase_busy_t), GFP_KERNEL); busy = kmalloc(sizeof(erase_busy_t), GFP_KERNEL);
if (!busy) if (!busy) {
return CS_GENERAL_FAILURE; erase->State = ERASE_FAILED;
return;
}
busy->erase = erase; busy->erase = erase;
busy->client = handle; busy->client = handle;
init_timer(&busy->timeout); init_timer(&busy->timeout);
...@@ -240,7 +242,6 @@ static int setup_erase_request(client_handle_t handle, eraseq_entry_t *erase) ...@@ -240,7 +242,6 @@ static int setup_erase_request(client_handle_t handle, eraseq_entry_t *erase)
retry_erase(busy, 0); retry_erase(busy, 0);
} }
} }
return CS_SUCCESS;
} /* setup_erase_request */ } /* setup_erase_request */
/*====================================================================== /*======================================================================
...@@ -325,7 +326,7 @@ int MTDHelperEntry(int func, void *a1, void *a2) ...@@ -325,7 +326,7 @@ int MTDHelperEntry(int func, void *a1, void *a2)
======================================================================*/ ======================================================================*/
static int setup_regions(client_handle_t handle, int attr, static void setup_regions(client_handle_t handle, int attr,
memory_handle_t *list) memory_handle_t *list)
{ {
int i, code, has_jedec, has_geo; int i, code, has_jedec, has_geo;
...@@ -340,7 +341,7 @@ static int setup_regions(client_handle_t handle, int attr, ...@@ -340,7 +341,7 @@ static int setup_regions(client_handle_t handle, int attr,
code = (attr) ? CISTPL_DEVICE_A : CISTPL_DEVICE; code = (attr) ? CISTPL_DEVICE_A : CISTPL_DEVICE;
if (read_tuple(handle, code, &device) != CS_SUCCESS) if (read_tuple(handle, code, &device) != CS_SUCCESS)
return CS_GENERAL_FAILURE; return;
code = (attr) ? CISTPL_JEDEC_A : CISTPL_JEDEC_C; code = (attr) ? CISTPL_JEDEC_A : CISTPL_JEDEC_C;
has_jedec = (read_tuple(handle, code, &jedec) == CS_SUCCESS); has_jedec = (read_tuple(handle, code, &jedec) == CS_SUCCESS);
if (has_jedec && (device.ndev != jedec.nid)) { if (has_jedec && (device.ndev != jedec.nid)) {
...@@ -363,8 +364,10 @@ static int setup_regions(client_handle_t handle, int attr, ...@@ -363,8 +364,10 @@ static int setup_regions(client_handle_t handle, int attr,
if ((device.dev[i].type != CISTPL_DTYPE_NULL) && if ((device.dev[i].type != CISTPL_DTYPE_NULL) &&
(device.dev[i].size != 0)) { (device.dev[i].size != 0)) {
r = kmalloc(sizeof(*r), GFP_KERNEL); r = kmalloc(sizeof(*r), GFP_KERNEL);
if (!r) if (!r) {
return CS_GENERAL_FAILURE; printk(KERN_NOTICE "cs: setup_regions: kmalloc failed!\n");
return;
}
r->region_magic = REGION_MAGIC; r->region_magic = REGION_MAGIC;
r->state = 0; r->state = 0;
r->dev_info[0] = '\0'; r->dev_info[0] = '\0';
...@@ -389,7 +392,6 @@ static int setup_regions(client_handle_t handle, int attr, ...@@ -389,7 +392,6 @@ static int setup_regions(client_handle_t handle, int attr,
} }
offset += device.dev[i].size; offset += device.dev[i].size;
} }
return CS_SUCCESS;
} /* setup_regions */ } /* setup_regions */
/*====================================================================== /*======================================================================
...@@ -423,10 +425,8 @@ int pcmcia_get_first_region(client_handle_t handle, region_info_t *rgn) ...@@ -423,10 +425,8 @@ int pcmcia_get_first_region(client_handle_t handle, region_info_t *rgn)
if ((handle->Attributes & INFO_MASTER_CLIENT) && if ((handle->Attributes & INFO_MASTER_CLIENT) &&
(!(s->state & SOCKET_REGION_INFO))) { (!(s->state & SOCKET_REGION_INFO))) {
if (setup_regions(handle, 0, &s->c_region) != CS_SUCCESS) setup_regions(handle, 0, &s->c_region);
return CS_GENERAL_FAILURE; setup_regions(handle, 1, &s->a_region);
if (setup_regions(handle, 1, &s->a_region) != CS_SUCCESS)
return CS_GENERAL_FAILURE;
s->state |= SOCKET_REGION_INFO; s->state |= SOCKET_REGION_INFO;
} }
......
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