diff options
Diffstat (limited to 'drivers/net/wireless/libertas/if_sdio.c')
| -rw-r--r-- | drivers/net/wireless/libertas/if_sdio.c | 159 | 
1 files changed, 59 insertions, 100 deletions
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 87b634978b3..296fd00a512 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -76,36 +76,32 @@ static const struct sdio_device_id if_sdio_ids[] = {  MODULE_DEVICE_TABLE(sdio, if_sdio_ids); -struct if_sdio_model { -	int model; -	const char *helper; -	const char *firmware; -}; +#define MODEL_8385	0x04 +#define MODEL_8686	0x0b +#define MODEL_8688	0x10 -static struct if_sdio_model if_sdio_models[] = { -	{ -		/* 8385 */ -		.model = IF_SDIO_MODEL_8385, -		.helper = "sd8385_helper.bin", -		.firmware = "sd8385.bin", -	}, -	{ -		/* 8686 */ -		.model = IF_SDIO_MODEL_8686, -		.helper = "sd8686_helper.bin", -		.firmware = "sd8686.bin", -	}, -	{ -		/* 8688 */ -		.model = IF_SDIO_MODEL_8688, -		.helper = "sd8688_helper.bin", -		.firmware = "sd8688.bin", -	}, +static const struct lbs_fw_table fw_table[] = { +	{ MODEL_8385, "libertas/sd8385_helper.bin", "libertas/sd8385.bin" }, +	{ MODEL_8385, "sd8385_helper.bin", "sd8385.bin" }, +	{ MODEL_8686, "libertas/sd8686_v9_helper.bin", "libertas/sd8686_v9.bin" }, +	{ MODEL_8686, "libertas/sd8686_v8_helper.bin", "libertas/sd8686_v8.bin" }, +	{ MODEL_8686, "sd8686_helper.bin", "sd8686.bin" }, +	{ MODEL_8688, "libertas/sd8688_helper.bin", "libertas/sd8688.bin" }, +	{ MODEL_8688, "sd8688_helper.bin", "sd8688.bin" }, +	{ 0, NULL, NULL }  }; +MODULE_FIRMWARE("libertas/sd8385_helper.bin"); +MODULE_FIRMWARE("libertas/sd8385.bin");  MODULE_FIRMWARE("sd8385_helper.bin");  MODULE_FIRMWARE("sd8385.bin"); +MODULE_FIRMWARE("libertas/sd8686_v9_helper.bin"); +MODULE_FIRMWARE("libertas/sd8686_v9.bin"); +MODULE_FIRMWARE("libertas/sd8686_v8_helper.bin"); +MODULE_FIRMWARE("libertas/sd8686_v8.bin");  MODULE_FIRMWARE("sd8686_helper.bin");  MODULE_FIRMWARE("sd8686.bin"); +MODULE_FIRMWARE("libertas/sd8688_helper.bin"); +MODULE_FIRMWARE("libertas/sd8688.bin");  MODULE_FIRMWARE("sd8688_helper.bin");  MODULE_FIRMWARE("sd8688.bin"); @@ -187,11 +183,11 @@ static u16 if_sdio_read_rx_len(struct if_sdio_card *card, int *err)  	u16 rx_len;  	switch (card->model) { -	case IF_SDIO_MODEL_8385: -	case IF_SDIO_MODEL_8686: +	case MODEL_8385: +	case MODEL_8686:  		rx_len = if_sdio_read_scratch(card, &ret);  		break; -	case IF_SDIO_MODEL_8688: +	case MODEL_8688:  	default: /* for newer chipsets */  		rx_len = sdio_readb(card->func, IF_SDIO_RX_LEN, &ret);  		if (!ret) @@ -288,7 +284,7 @@ static int if_sdio_handle_event(struct if_sdio_card *card,  	lbs_deb_enter(LBS_DEB_SDIO); -	if (card->model == IF_SDIO_MODEL_8385) { +	if (card->model == MODEL_8385) {  		event = sdio_readb(card->func, IF_SDIO_EVENT, &ret);  		if (ret)  			goto out; @@ -466,10 +462,10 @@ static void if_sdio_host_to_card_worker(struct work_struct *work)  #define FW_DL_READY_STATUS (IF_SDIO_IO_RDY | IF_SDIO_DL_RDY) -static int if_sdio_prog_helper(struct if_sdio_card *card) +static int if_sdio_prog_helper(struct if_sdio_card *card, +				const struct firmware *fw)  {  	int ret; -	const struct firmware *fw;  	unsigned long timeout;  	u8 *chunk_buffer;  	u32 chunk_size; @@ -478,16 +474,10 @@ static int if_sdio_prog_helper(struct if_sdio_card *card)  	lbs_deb_enter(LBS_DEB_SDIO); -	ret = request_firmware(&fw, card->helper, &card->func->dev); -	if (ret) { -		lbs_pr_err("can't load helper firmware\n"); -		goto out; -	} -  	chunk_buffer = kzalloc(64, GFP_KERNEL);  	if (!chunk_buffer) {  		ret = -ENOMEM; -		goto release_fw; +		goto out;  	}  	sdio_claim_host(card->func); @@ -562,22 +552,19 @@ static int if_sdio_prog_helper(struct if_sdio_card *card)  release:  	sdio_release_host(card->func);  	kfree(chunk_buffer); -release_fw: -	release_firmware(fw);  out:  	if (ret)  		lbs_pr_err("failed to load helper firmware\n");  	lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); -  	return ret;  } -static int if_sdio_prog_real(struct if_sdio_card *card) +static int if_sdio_prog_real(struct if_sdio_card *card, +				const struct firmware *fw)  {  	int ret; -	const struct firmware *fw;  	unsigned long timeout;  	u8 *chunk_buffer;  	u32 chunk_size; @@ -586,16 +573,10 @@ static int if_sdio_prog_real(struct if_sdio_card *card)  	lbs_deb_enter(LBS_DEB_SDIO); -	ret = request_firmware(&fw, card->firmware, &card->func->dev); -	if (ret) { -		lbs_pr_err("can't load firmware\n"); -		goto out; -	} -  	chunk_buffer = kzalloc(512, GFP_KERNEL);  	if (!chunk_buffer) {  		ret = -ENOMEM; -		goto release_fw; +		goto out;  	}  	sdio_claim_host(card->func); @@ -685,15 +666,12 @@ static int if_sdio_prog_real(struct if_sdio_card *card)  release:  	sdio_release_host(card->func);  	kfree(chunk_buffer); -release_fw: -	release_firmware(fw);  out:  	if (ret)  		lbs_pr_err("failed to load firmware\n");  	lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); -  	return ret;  } @@ -701,6 +679,8 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)  {  	int ret;  	u16 scratch; +	const struct firmware *helper = NULL; +	const struct firmware *mainfw = NULL;  	lbs_deb_enter(LBS_DEB_SDIO); @@ -718,11 +698,18 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)  		goto success;  	} -	ret = if_sdio_prog_helper(card); +	ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name, +				card->model, &fw_table[0], &helper, &mainfw); +	if (ret) { +		lbs_pr_err("failed to find firmware (%d)\n", ret); +		goto out; +	} + +	ret = if_sdio_prog_helper(card, helper);  	if (ret)  		goto out; -	ret = if_sdio_prog_real(card); +	ret = if_sdio_prog_real(card, mainfw);  	if (ret)  		goto out; @@ -733,8 +720,12 @@ success:  	ret = 0;  out: -	lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); +	if (helper) +		release_firmware(helper); +	if (mainfw) +		release_firmware(mainfw); +	lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);  	return ret;  } @@ -938,7 +929,7 @@ static int if_sdio_probe(struct sdio_func *func,  				"ID: %x", &model) == 1)  			break;  		if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) { -			model = IF_SDIO_MODEL_8385; +			model = MODEL_8385;  			break;  		}  	} @@ -956,13 +947,13 @@ static int if_sdio_probe(struct sdio_func *func,  	card->model = model;  	switch (card->model) { -	case IF_SDIO_MODEL_8385: +	case MODEL_8385:  		card->scratch_reg = IF_SDIO_SCRATCH_OLD;  		break; -	case IF_SDIO_MODEL_8686: +	case MODEL_8686:  		card->scratch_reg = IF_SDIO_SCRATCH;  		break; -	case IF_SDIO_MODEL_8688: +	case MODEL_8688:  	default: /* for newer chipsets */  		card->scratch_reg = IF_SDIO_FW_STATUS;  		break; @@ -972,49 +963,17 @@ static int if_sdio_probe(struct sdio_func *func,  	card->workqueue = create_workqueue("libertas_sdio");  	INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); -	for (i = 0;i < ARRAY_SIZE(if_sdio_models);i++) { -		if (card->model == if_sdio_models[i].model) +	/* Check if we support this card */ +	for (i = 0; i < ARRAY_SIZE(fw_table); i++) { +		if (card->model == fw_table[i].model)  			break;  	} - -	if (i == ARRAY_SIZE(if_sdio_models)) { +	if (i == ARRAY_SIZE(fw_table)) {  		lbs_pr_err("unknown card model 0x%x\n", card->model);  		ret = -ENODEV;  		goto free;  	} -	card->helper = if_sdio_models[i].helper; -	card->firmware = if_sdio_models[i].firmware; - -	kparam_block_sysfs_write(helper_name); -	if (lbs_helper_name) { -		char *helper = kstrdup(lbs_helper_name, GFP_KERNEL); -		if (!helper) { -			kparam_unblock_sysfs_write(helper_name); -			ret = -ENOMEM; -			goto free; -		} -		lbs_deb_sdio("overriding helper firmware: %s\n", -			lbs_helper_name); -		card->helper = helper; -		card->helper_allocated = true; -	} -	kparam_unblock_sysfs_write(helper_name); - -	kparam_block_sysfs_write(fw_name); -	if (lbs_fw_name) { -		char *fw_name = kstrdup(lbs_fw_name, GFP_KERNEL); -		if (!fw_name) { -			kparam_unblock_sysfs_write(fw_name); -			ret = -ENOMEM; -			goto free; -		} -		lbs_deb_sdio("overriding firmware: %s\n", lbs_fw_name); -		card->firmware = fw_name; -		card->firmware_allocated = true; -	} -	kparam_unblock_sysfs_write(fw_name); -  	sdio_claim_host(func);  	ret = sdio_enable_func(func); @@ -1028,7 +987,7 @@ static int if_sdio_probe(struct sdio_func *func,  	/* For 1-bit transfers to the 8686 model, we need to enable the  	 * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0  	 * bit to allow access to non-vendor registers. */ -	if ((card->model == IF_SDIO_MODEL_8686) && +	if ((card->model == MODEL_8686) &&  	    (host->caps & MMC_CAP_SDIO_IRQ) &&  	    (host->ios.bus_width == MMC_BUS_WIDTH_1)) {  		u8 reg; @@ -1091,8 +1050,8 @@ static int if_sdio_probe(struct sdio_func *func,  	 * Get rx_unit if the chip is SD8688 or newer.  	 * SD8385 & SD8686 do not have rx_unit.  	 */ -	if ((card->model != IF_SDIO_MODEL_8385) -			&& (card->model != IF_SDIO_MODEL_8686)) +	if ((card->model != MODEL_8385) +			&& (card->model != MODEL_8686))  		card->rx_unit = if_sdio_read_rx_unit(card);  	else  		card->rx_unit = 0; @@ -1108,7 +1067,7 @@ static int if_sdio_probe(struct sdio_func *func,  	/*  	 * FUNC_INIT is required for SD8688 WLAN/BT multiple functions  	 */ -	if (card->model == IF_SDIO_MODEL_8688) { +	if (card->model == MODEL_8688) {  		struct cmd_header cmd;  		memset(&cmd, 0, sizeof(cmd)); @@ -1165,7 +1124,7 @@ static void if_sdio_remove(struct sdio_func *func)  	card = sdio_get_drvdata(func); -	if (user_rmmod && (card->model == IF_SDIO_MODEL_8688)) { +	if (user_rmmod && (card->model == MODEL_8688)) {  		/*  		 * FUNC_SHUTDOWN is required for SD8688 WLAN/BT  		 * multiple functions  |