xref: /OK3568_Linux_fs/kernel/drivers/block/ps3disk.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * PS3 Disk Storage Driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2007 Sony Computer Entertainment Inc.
6*4882a593Smuzhiyun  * Copyright 2007 Sony Corp.
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <linux/ata.h>
10*4882a593Smuzhiyun #include <linux/blk-mq.h>
11*4882a593Smuzhiyun #include <linux/slab.h>
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <asm/lv1call.h>
15*4882a593Smuzhiyun #include <asm/ps3stor.h>
16*4882a593Smuzhiyun #include <asm/firmware.h>
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #define DEVICE_NAME		"ps3disk"
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define BOUNCE_SIZE		(64*1024)
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #define PS3DISK_MAX_DISKS	16
24*4882a593Smuzhiyun #define PS3DISK_MINORS		16
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #define PS3DISK_NAME		"ps3d%c"
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun struct ps3disk_private {
31*4882a593Smuzhiyun 	spinlock_t lock;		/* Request queue spinlock */
32*4882a593Smuzhiyun 	struct request_queue *queue;
33*4882a593Smuzhiyun 	struct blk_mq_tag_set tag_set;
34*4882a593Smuzhiyun 	struct gendisk *gendisk;
35*4882a593Smuzhiyun 	unsigned int blocking_factor;
36*4882a593Smuzhiyun 	struct request *req;
37*4882a593Smuzhiyun 	u64 raw_capacity;
38*4882a593Smuzhiyun 	unsigned char model[ATA_ID_PROD_LEN+1];
39*4882a593Smuzhiyun };
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun #define LV1_STORAGE_SEND_ATA_COMMAND	(2)
43*4882a593Smuzhiyun #define LV1_STORAGE_ATA_HDDOUT		(0x23)
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun struct lv1_ata_cmnd_block {
46*4882a593Smuzhiyun 	u16	features;
47*4882a593Smuzhiyun 	u16	sector_count;
48*4882a593Smuzhiyun 	u16	LBA_low;
49*4882a593Smuzhiyun 	u16	LBA_mid;
50*4882a593Smuzhiyun 	u16	LBA_high;
51*4882a593Smuzhiyun 	u8	device;
52*4882a593Smuzhiyun 	u8	command;
53*4882a593Smuzhiyun 	u32	is_ext;
54*4882a593Smuzhiyun 	u32	proto;
55*4882a593Smuzhiyun 	u32	in_out;
56*4882a593Smuzhiyun 	u32	size;
57*4882a593Smuzhiyun 	u64	buffer;
58*4882a593Smuzhiyun 	u32	arglen;
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun enum lv1_ata_proto {
62*4882a593Smuzhiyun 	NON_DATA_PROTO     = 0,
63*4882a593Smuzhiyun 	PIO_DATA_IN_PROTO  = 1,
64*4882a593Smuzhiyun 	PIO_DATA_OUT_PROTO = 2,
65*4882a593Smuzhiyun 	DMA_PROTO = 3
66*4882a593Smuzhiyun };
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun enum lv1_ata_in_out {
69*4882a593Smuzhiyun 	DIR_WRITE = 0,			/* memory -> device */
70*4882a593Smuzhiyun 	DIR_READ = 1			/* device -> memory */
71*4882a593Smuzhiyun };
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun static int ps3disk_major;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun static const struct block_device_operations ps3disk_fops = {
77*4882a593Smuzhiyun 	.owner		= THIS_MODULE,
78*4882a593Smuzhiyun };
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 
ps3disk_scatter_gather(struct ps3_storage_device * dev,struct request * req,int gather)81*4882a593Smuzhiyun static void ps3disk_scatter_gather(struct ps3_storage_device *dev,
82*4882a593Smuzhiyun 				   struct request *req, int gather)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun 	unsigned int offset = 0;
85*4882a593Smuzhiyun 	struct req_iterator iter;
86*4882a593Smuzhiyun 	struct bio_vec bvec;
87*4882a593Smuzhiyun 	unsigned int i = 0;
88*4882a593Smuzhiyun 	size_t size;
89*4882a593Smuzhiyun 	void *buf;
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	rq_for_each_segment(bvec, req, iter) {
92*4882a593Smuzhiyun 		unsigned long flags;
93*4882a593Smuzhiyun 		dev_dbg(&dev->sbd.core, "%s:%u: bio %u: %u sectors from %llu\n",
94*4882a593Smuzhiyun 			__func__, __LINE__, i, bio_sectors(iter.bio),
95*4882a593Smuzhiyun 			iter.bio->bi_iter.bi_sector);
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 		size = bvec.bv_len;
98*4882a593Smuzhiyun 		buf = bvec_kmap_irq(&bvec, &flags);
99*4882a593Smuzhiyun 		if (gather)
100*4882a593Smuzhiyun 			memcpy(dev->bounce_buf+offset, buf, size);
101*4882a593Smuzhiyun 		else
102*4882a593Smuzhiyun 			memcpy(buf, dev->bounce_buf+offset, size);
103*4882a593Smuzhiyun 		offset += size;
104*4882a593Smuzhiyun 		flush_kernel_dcache_page(bvec.bv_page);
105*4882a593Smuzhiyun 		bvec_kunmap_irq(buf, &flags);
106*4882a593Smuzhiyun 		i++;
107*4882a593Smuzhiyun 	}
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun 
ps3disk_submit_request_sg(struct ps3_storage_device * dev,struct request * req)110*4882a593Smuzhiyun static blk_status_t ps3disk_submit_request_sg(struct ps3_storage_device *dev,
111*4882a593Smuzhiyun 					      struct request *req)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun 	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
114*4882a593Smuzhiyun 	int write = rq_data_dir(req), res;
115*4882a593Smuzhiyun 	const char *op = write ? "write" : "read";
116*4882a593Smuzhiyun 	u64 start_sector, sectors;
117*4882a593Smuzhiyun 	unsigned int region_id = dev->regions[dev->region_idx].id;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun #ifdef DEBUG
120*4882a593Smuzhiyun 	unsigned int n = 0;
121*4882a593Smuzhiyun 	struct bio_vec bv;
122*4882a593Smuzhiyun 	struct req_iterator iter;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	rq_for_each_segment(bv, req, iter)
125*4882a593Smuzhiyun 		n++;
126*4882a593Smuzhiyun 	dev_dbg(&dev->sbd.core,
127*4882a593Smuzhiyun 		"%s:%u: %s req has %u bvecs for %u sectors\n",
128*4882a593Smuzhiyun 		__func__, __LINE__, op, n, blk_rq_sectors(req));
129*4882a593Smuzhiyun #endif
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	start_sector = blk_rq_pos(req) * priv->blocking_factor;
132*4882a593Smuzhiyun 	sectors = blk_rq_sectors(req) * priv->blocking_factor;
133*4882a593Smuzhiyun 	dev_dbg(&dev->sbd.core, "%s:%u: %s %llu sectors starting at %llu\n",
134*4882a593Smuzhiyun 		__func__, __LINE__, op, sectors, start_sector);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	if (write) {
137*4882a593Smuzhiyun 		ps3disk_scatter_gather(dev, req, 1);
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 		res = lv1_storage_write(dev->sbd.dev_id, region_id,
140*4882a593Smuzhiyun 					start_sector, sectors, 0,
141*4882a593Smuzhiyun 					dev->bounce_lpar, &dev->tag);
142*4882a593Smuzhiyun 	} else {
143*4882a593Smuzhiyun 		res = lv1_storage_read(dev->sbd.dev_id, region_id,
144*4882a593Smuzhiyun 				       start_sector, sectors, 0,
145*4882a593Smuzhiyun 				       dev->bounce_lpar, &dev->tag);
146*4882a593Smuzhiyun 	}
147*4882a593Smuzhiyun 	if (res) {
148*4882a593Smuzhiyun 		dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
149*4882a593Smuzhiyun 			__LINE__, op, res);
150*4882a593Smuzhiyun 		return BLK_STS_IOERR;
151*4882a593Smuzhiyun 	}
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	priv->req = req;
154*4882a593Smuzhiyun 	return BLK_STS_OK;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun 
ps3disk_submit_flush_request(struct ps3_storage_device * dev,struct request * req)157*4882a593Smuzhiyun static blk_status_t ps3disk_submit_flush_request(struct ps3_storage_device *dev,
158*4882a593Smuzhiyun 						 struct request *req)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun 	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
161*4882a593Smuzhiyun 	u64 res;
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	dev_dbg(&dev->sbd.core, "%s:%u: flush request\n", __func__, __LINE__);
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	res = lv1_storage_send_device_command(dev->sbd.dev_id,
166*4882a593Smuzhiyun 					      LV1_STORAGE_ATA_HDDOUT, 0, 0, 0,
167*4882a593Smuzhiyun 					      0, &dev->tag);
168*4882a593Smuzhiyun 	if (res) {
169*4882a593Smuzhiyun 		dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n",
170*4882a593Smuzhiyun 			__func__, __LINE__, res);
171*4882a593Smuzhiyun 		return BLK_STS_IOERR;
172*4882a593Smuzhiyun 	}
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	priv->req = req;
175*4882a593Smuzhiyun 	return BLK_STS_OK;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun 
ps3disk_do_request(struct ps3_storage_device * dev,struct request * req)178*4882a593Smuzhiyun static blk_status_t ps3disk_do_request(struct ps3_storage_device *dev,
179*4882a593Smuzhiyun 				       struct request *req)
180*4882a593Smuzhiyun {
181*4882a593Smuzhiyun 	dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	switch (req_op(req)) {
184*4882a593Smuzhiyun 	case REQ_OP_FLUSH:
185*4882a593Smuzhiyun 		return ps3disk_submit_flush_request(dev, req);
186*4882a593Smuzhiyun 	case REQ_OP_READ:
187*4882a593Smuzhiyun 	case REQ_OP_WRITE:
188*4882a593Smuzhiyun 		return ps3disk_submit_request_sg(dev, req);
189*4882a593Smuzhiyun 	default:
190*4882a593Smuzhiyun 		blk_dump_rq_flags(req, DEVICE_NAME " bad request");
191*4882a593Smuzhiyun 		return BLK_STS_IOERR;
192*4882a593Smuzhiyun 	}
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun 
ps3disk_queue_rq(struct blk_mq_hw_ctx * hctx,const struct blk_mq_queue_data * bd)195*4882a593Smuzhiyun static blk_status_t ps3disk_queue_rq(struct blk_mq_hw_ctx *hctx,
196*4882a593Smuzhiyun 				     const struct blk_mq_queue_data *bd)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun 	struct request_queue *q = hctx->queue;
199*4882a593Smuzhiyun 	struct ps3_storage_device *dev = q->queuedata;
200*4882a593Smuzhiyun 	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
201*4882a593Smuzhiyun 	blk_status_t ret;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	blk_mq_start_request(bd->rq);
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	spin_lock_irq(&priv->lock);
206*4882a593Smuzhiyun 	ret = ps3disk_do_request(dev, bd->rq);
207*4882a593Smuzhiyun 	spin_unlock_irq(&priv->lock);
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	return ret;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
ps3disk_interrupt(int irq,void * data)212*4882a593Smuzhiyun static irqreturn_t ps3disk_interrupt(int irq, void *data)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	struct ps3_storage_device *dev = data;
215*4882a593Smuzhiyun 	struct ps3disk_private *priv;
216*4882a593Smuzhiyun 	struct request *req;
217*4882a593Smuzhiyun 	int res, read;
218*4882a593Smuzhiyun 	blk_status_t error;
219*4882a593Smuzhiyun 	u64 tag, status;
220*4882a593Smuzhiyun 	const char *op;
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	if (tag != dev->tag)
225*4882a593Smuzhiyun 		dev_err(&dev->sbd.core,
226*4882a593Smuzhiyun 			"%s:%u: tag mismatch, got %llx, expected %llx\n",
227*4882a593Smuzhiyun 			__func__, __LINE__, tag, dev->tag);
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	if (res) {
230*4882a593Smuzhiyun 		dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx\n",
231*4882a593Smuzhiyun 			__func__, __LINE__, res, status);
232*4882a593Smuzhiyun 		return IRQ_HANDLED;
233*4882a593Smuzhiyun 	}
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	priv = ps3_system_bus_get_drvdata(&dev->sbd);
236*4882a593Smuzhiyun 	req = priv->req;
237*4882a593Smuzhiyun 	if (!req) {
238*4882a593Smuzhiyun 		dev_dbg(&dev->sbd.core,
239*4882a593Smuzhiyun 			"%s:%u non-block layer request completed\n", __func__,
240*4882a593Smuzhiyun 			__LINE__);
241*4882a593Smuzhiyun 		dev->lv1_status = status;
242*4882a593Smuzhiyun 		complete(&dev->done);
243*4882a593Smuzhiyun 		return IRQ_HANDLED;
244*4882a593Smuzhiyun 	}
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	if (req_op(req) == REQ_OP_FLUSH) {
247*4882a593Smuzhiyun 		read = 0;
248*4882a593Smuzhiyun 		op = "flush";
249*4882a593Smuzhiyun 	} else {
250*4882a593Smuzhiyun 		read = !rq_data_dir(req);
251*4882a593Smuzhiyun 		op = read ? "read" : "write";
252*4882a593Smuzhiyun 	}
253*4882a593Smuzhiyun 	if (status) {
254*4882a593Smuzhiyun 		dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%llx\n", __func__,
255*4882a593Smuzhiyun 			__LINE__, op, status);
256*4882a593Smuzhiyun 		error = BLK_STS_IOERR;
257*4882a593Smuzhiyun 	} else {
258*4882a593Smuzhiyun 		dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__,
259*4882a593Smuzhiyun 			__LINE__, op);
260*4882a593Smuzhiyun 		error = 0;
261*4882a593Smuzhiyun 		if (read)
262*4882a593Smuzhiyun 			ps3disk_scatter_gather(dev, req, 0);
263*4882a593Smuzhiyun 	}
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	spin_lock(&priv->lock);
266*4882a593Smuzhiyun 	priv->req = NULL;
267*4882a593Smuzhiyun 	blk_mq_end_request(req, error);
268*4882a593Smuzhiyun 	spin_unlock(&priv->lock);
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	blk_mq_run_hw_queues(priv->queue, true);
271*4882a593Smuzhiyun 	return IRQ_HANDLED;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun 
ps3disk_sync_cache(struct ps3_storage_device * dev)274*4882a593Smuzhiyun static int ps3disk_sync_cache(struct ps3_storage_device *dev)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun 	u64 res;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	dev_dbg(&dev->sbd.core, "%s:%u: sync cache\n", __func__, __LINE__);
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	res = ps3stor_send_command(dev, LV1_STORAGE_ATA_HDDOUT, 0, 0, 0, 0);
281*4882a593Smuzhiyun 	if (res) {
282*4882a593Smuzhiyun 		dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n",
283*4882a593Smuzhiyun 			__func__, __LINE__, res);
284*4882a593Smuzhiyun 		return -EIO;
285*4882a593Smuzhiyun 	}
286*4882a593Smuzhiyun 	return 0;
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun /* ATA helpers copied from drivers/ata/libata-core.c */
291*4882a593Smuzhiyun 
swap_buf_le16(u16 * buf,unsigned int buf_words)292*4882a593Smuzhiyun static void swap_buf_le16(u16 *buf, unsigned int buf_words)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun #ifdef __BIG_ENDIAN
295*4882a593Smuzhiyun 	unsigned int i;
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	for (i = 0; i < buf_words; i++)
298*4882a593Smuzhiyun 		buf[i] = le16_to_cpu(buf[i]);
299*4882a593Smuzhiyun #endif /* __BIG_ENDIAN */
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun 
ata_id_n_sectors(const u16 * id)302*4882a593Smuzhiyun static u64 ata_id_n_sectors(const u16 *id)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun 	if (ata_id_has_lba(id)) {
305*4882a593Smuzhiyun 		if (ata_id_has_lba48(id))
306*4882a593Smuzhiyun 			return ata_id_u64(id, 100);
307*4882a593Smuzhiyun 		else
308*4882a593Smuzhiyun 			return ata_id_u32(id, 60);
309*4882a593Smuzhiyun 	} else {
310*4882a593Smuzhiyun 		if (ata_id_current_chs_valid(id))
311*4882a593Smuzhiyun 			return ata_id_u32(id, 57);
312*4882a593Smuzhiyun 		else
313*4882a593Smuzhiyun 			return id[1] * id[3] * id[6];
314*4882a593Smuzhiyun 	}
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun 
ata_id_string(const u16 * id,unsigned char * s,unsigned int ofs,unsigned int len)317*4882a593Smuzhiyun static void ata_id_string(const u16 *id, unsigned char *s, unsigned int ofs,
318*4882a593Smuzhiyun 			  unsigned int len)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun 	unsigned int c;
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	while (len > 0) {
323*4882a593Smuzhiyun 		c = id[ofs] >> 8;
324*4882a593Smuzhiyun 		*s = c;
325*4882a593Smuzhiyun 		s++;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 		c = id[ofs] & 0xff;
328*4882a593Smuzhiyun 		*s = c;
329*4882a593Smuzhiyun 		s++;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 		ofs++;
332*4882a593Smuzhiyun 		len -= 2;
333*4882a593Smuzhiyun 	}
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun 
ata_id_c_string(const u16 * id,unsigned char * s,unsigned int ofs,unsigned int len)336*4882a593Smuzhiyun static void ata_id_c_string(const u16 *id, unsigned char *s, unsigned int ofs,
337*4882a593Smuzhiyun 			    unsigned int len)
338*4882a593Smuzhiyun {
339*4882a593Smuzhiyun 	unsigned char *p;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	WARN_ON(!(len & 1));
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	ata_id_string(id, s, ofs, len - 1);
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	p = s + strnlen(s, len - 1);
346*4882a593Smuzhiyun 	while (p > s && p[-1] == ' ')
347*4882a593Smuzhiyun 		p--;
348*4882a593Smuzhiyun 	*p = '\0';
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun 
ps3disk_identify(struct ps3_storage_device * dev)351*4882a593Smuzhiyun static int ps3disk_identify(struct ps3_storage_device *dev)
352*4882a593Smuzhiyun {
353*4882a593Smuzhiyun 	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
354*4882a593Smuzhiyun 	struct lv1_ata_cmnd_block ata_cmnd;
355*4882a593Smuzhiyun 	u16 *id = dev->bounce_buf;
356*4882a593Smuzhiyun 	u64 res;
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	dev_dbg(&dev->sbd.core, "%s:%u: identify disk\n", __func__, __LINE__);
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	memset(&ata_cmnd, 0, sizeof(struct lv1_ata_cmnd_block));
361*4882a593Smuzhiyun 	ata_cmnd.command = ATA_CMD_ID_ATA;
362*4882a593Smuzhiyun 	ata_cmnd.sector_count = 1;
363*4882a593Smuzhiyun 	ata_cmnd.size = ata_cmnd.arglen = ATA_ID_WORDS * 2;
364*4882a593Smuzhiyun 	ata_cmnd.buffer = dev->bounce_lpar;
365*4882a593Smuzhiyun 	ata_cmnd.proto = PIO_DATA_IN_PROTO;
366*4882a593Smuzhiyun 	ata_cmnd.in_out = DIR_READ;
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	res = ps3stor_send_command(dev, LV1_STORAGE_SEND_ATA_COMMAND,
369*4882a593Smuzhiyun 				   ps3_mm_phys_to_lpar(__pa(&ata_cmnd)),
370*4882a593Smuzhiyun 				   sizeof(ata_cmnd), ata_cmnd.buffer,
371*4882a593Smuzhiyun 				   ata_cmnd.arglen);
372*4882a593Smuzhiyun 	if (res) {
373*4882a593Smuzhiyun 		dev_err(&dev->sbd.core, "%s:%u: identify disk failed 0x%llx\n",
374*4882a593Smuzhiyun 			__func__, __LINE__, res);
375*4882a593Smuzhiyun 		return -EIO;
376*4882a593Smuzhiyun 	}
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	swap_buf_le16(id, ATA_ID_WORDS);
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	/* All we're interested in are raw capacity and model name */
381*4882a593Smuzhiyun 	priv->raw_capacity = ata_id_n_sectors(id);
382*4882a593Smuzhiyun 	ata_id_c_string(id, priv->model, ATA_ID_PROD, sizeof(priv->model));
383*4882a593Smuzhiyun 	return 0;
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun static unsigned long ps3disk_mask;
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun static DEFINE_MUTEX(ps3disk_mask_mutex);
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun static const struct blk_mq_ops ps3disk_mq_ops = {
391*4882a593Smuzhiyun 	.queue_rq	= ps3disk_queue_rq,
392*4882a593Smuzhiyun };
393*4882a593Smuzhiyun 
ps3disk_probe(struct ps3_system_bus_device * _dev)394*4882a593Smuzhiyun static int ps3disk_probe(struct ps3_system_bus_device *_dev)
395*4882a593Smuzhiyun {
396*4882a593Smuzhiyun 	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
397*4882a593Smuzhiyun 	struct ps3disk_private *priv;
398*4882a593Smuzhiyun 	int error;
399*4882a593Smuzhiyun 	unsigned int devidx;
400*4882a593Smuzhiyun 	struct request_queue *queue;
401*4882a593Smuzhiyun 	struct gendisk *gendisk;
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	if (dev->blk_size < 512) {
404*4882a593Smuzhiyun 		dev_err(&dev->sbd.core,
405*4882a593Smuzhiyun 			"%s:%u: cannot handle block size %llu\n", __func__,
406*4882a593Smuzhiyun 			__LINE__, dev->blk_size);
407*4882a593Smuzhiyun 		return -EINVAL;
408*4882a593Smuzhiyun 	}
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	BUILD_BUG_ON(PS3DISK_MAX_DISKS > BITS_PER_LONG);
411*4882a593Smuzhiyun 	mutex_lock(&ps3disk_mask_mutex);
412*4882a593Smuzhiyun 	devidx = find_first_zero_bit(&ps3disk_mask, PS3DISK_MAX_DISKS);
413*4882a593Smuzhiyun 	if (devidx >= PS3DISK_MAX_DISKS) {
414*4882a593Smuzhiyun 		dev_err(&dev->sbd.core, "%s:%u: Too many disks\n", __func__,
415*4882a593Smuzhiyun 			__LINE__);
416*4882a593Smuzhiyun 		mutex_unlock(&ps3disk_mask_mutex);
417*4882a593Smuzhiyun 		return -ENOSPC;
418*4882a593Smuzhiyun 	}
419*4882a593Smuzhiyun 	__set_bit(devidx, &ps3disk_mask);
420*4882a593Smuzhiyun 	mutex_unlock(&ps3disk_mask_mutex);
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
423*4882a593Smuzhiyun 	if (!priv) {
424*4882a593Smuzhiyun 		error = -ENOMEM;
425*4882a593Smuzhiyun 		goto fail;
426*4882a593Smuzhiyun 	}
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	ps3_system_bus_set_drvdata(_dev, priv);
429*4882a593Smuzhiyun 	spin_lock_init(&priv->lock);
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 	dev->bounce_size = BOUNCE_SIZE;
432*4882a593Smuzhiyun 	dev->bounce_buf = kmalloc(BOUNCE_SIZE, GFP_DMA);
433*4882a593Smuzhiyun 	if (!dev->bounce_buf) {
434*4882a593Smuzhiyun 		error = -ENOMEM;
435*4882a593Smuzhiyun 		goto fail_free_priv;
436*4882a593Smuzhiyun 	}
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	error = ps3stor_setup(dev, ps3disk_interrupt);
439*4882a593Smuzhiyun 	if (error)
440*4882a593Smuzhiyun 		goto fail_free_bounce;
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	ps3disk_identify(dev);
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	queue = blk_mq_init_sq_queue(&priv->tag_set, &ps3disk_mq_ops, 1,
445*4882a593Smuzhiyun 					BLK_MQ_F_SHOULD_MERGE);
446*4882a593Smuzhiyun 	if (IS_ERR(queue)) {
447*4882a593Smuzhiyun 		dev_err(&dev->sbd.core, "%s:%u: blk_mq_init_queue failed\n",
448*4882a593Smuzhiyun 			__func__, __LINE__);
449*4882a593Smuzhiyun 		error = PTR_ERR(queue);
450*4882a593Smuzhiyun 		goto fail_teardown;
451*4882a593Smuzhiyun 	}
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	priv->queue = queue;
454*4882a593Smuzhiyun 	queue->queuedata = dev;
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 	blk_queue_max_hw_sectors(queue, dev->bounce_size >> 9);
457*4882a593Smuzhiyun 	blk_queue_dma_alignment(queue, dev->blk_size-1);
458*4882a593Smuzhiyun 	blk_queue_logical_block_size(queue, dev->blk_size);
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	blk_queue_write_cache(queue, true, false);
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	blk_queue_max_segments(queue, -1);
463*4882a593Smuzhiyun 	blk_queue_max_segment_size(queue, dev->bounce_size);
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	gendisk = alloc_disk(PS3DISK_MINORS);
466*4882a593Smuzhiyun 	if (!gendisk) {
467*4882a593Smuzhiyun 		dev_err(&dev->sbd.core, "%s:%u: alloc_disk failed\n", __func__,
468*4882a593Smuzhiyun 			__LINE__);
469*4882a593Smuzhiyun 		error = -ENOMEM;
470*4882a593Smuzhiyun 		goto fail_cleanup_queue;
471*4882a593Smuzhiyun 	}
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun 	priv->gendisk = gendisk;
474*4882a593Smuzhiyun 	gendisk->major = ps3disk_major;
475*4882a593Smuzhiyun 	gendisk->first_minor = devidx * PS3DISK_MINORS;
476*4882a593Smuzhiyun 	gendisk->fops = &ps3disk_fops;
477*4882a593Smuzhiyun 	gendisk->queue = queue;
478*4882a593Smuzhiyun 	gendisk->private_data = dev;
479*4882a593Smuzhiyun 	snprintf(gendisk->disk_name, sizeof(gendisk->disk_name), PS3DISK_NAME,
480*4882a593Smuzhiyun 		 devidx+'a');
481*4882a593Smuzhiyun 	priv->blocking_factor = dev->blk_size >> 9;
482*4882a593Smuzhiyun 	set_capacity(gendisk,
483*4882a593Smuzhiyun 		     dev->regions[dev->region_idx].size*priv->blocking_factor);
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 	dev_info(&dev->sbd.core,
486*4882a593Smuzhiyun 		 "%s is a %s (%llu MiB total, %llu MiB for OtherOS)\n",
487*4882a593Smuzhiyun 		 gendisk->disk_name, priv->model, priv->raw_capacity >> 11,
488*4882a593Smuzhiyun 		 get_capacity(gendisk) >> 11);
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	device_add_disk(&dev->sbd.core, gendisk, NULL);
491*4882a593Smuzhiyun 	return 0;
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun fail_cleanup_queue:
494*4882a593Smuzhiyun 	blk_cleanup_queue(queue);
495*4882a593Smuzhiyun 	blk_mq_free_tag_set(&priv->tag_set);
496*4882a593Smuzhiyun fail_teardown:
497*4882a593Smuzhiyun 	ps3stor_teardown(dev);
498*4882a593Smuzhiyun fail_free_bounce:
499*4882a593Smuzhiyun 	kfree(dev->bounce_buf);
500*4882a593Smuzhiyun fail_free_priv:
501*4882a593Smuzhiyun 	kfree(priv);
502*4882a593Smuzhiyun 	ps3_system_bus_set_drvdata(_dev, NULL);
503*4882a593Smuzhiyun fail:
504*4882a593Smuzhiyun 	mutex_lock(&ps3disk_mask_mutex);
505*4882a593Smuzhiyun 	__clear_bit(devidx, &ps3disk_mask);
506*4882a593Smuzhiyun 	mutex_unlock(&ps3disk_mask_mutex);
507*4882a593Smuzhiyun 	return error;
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun 
ps3disk_remove(struct ps3_system_bus_device * _dev)510*4882a593Smuzhiyun static int ps3disk_remove(struct ps3_system_bus_device *_dev)
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun 	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
513*4882a593Smuzhiyun 	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	mutex_lock(&ps3disk_mask_mutex);
516*4882a593Smuzhiyun 	__clear_bit(MINOR(disk_devt(priv->gendisk)) / PS3DISK_MINORS,
517*4882a593Smuzhiyun 		    &ps3disk_mask);
518*4882a593Smuzhiyun 	mutex_unlock(&ps3disk_mask_mutex);
519*4882a593Smuzhiyun 	del_gendisk(priv->gendisk);
520*4882a593Smuzhiyun 	blk_cleanup_queue(priv->queue);
521*4882a593Smuzhiyun 	blk_mq_free_tag_set(&priv->tag_set);
522*4882a593Smuzhiyun 	put_disk(priv->gendisk);
523*4882a593Smuzhiyun 	dev_notice(&dev->sbd.core, "Synchronizing disk cache\n");
524*4882a593Smuzhiyun 	ps3disk_sync_cache(dev);
525*4882a593Smuzhiyun 	ps3stor_teardown(dev);
526*4882a593Smuzhiyun 	kfree(dev->bounce_buf);
527*4882a593Smuzhiyun 	kfree(priv);
528*4882a593Smuzhiyun 	ps3_system_bus_set_drvdata(_dev, NULL);
529*4882a593Smuzhiyun 	return 0;
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun static struct ps3_system_bus_driver ps3disk = {
533*4882a593Smuzhiyun 	.match_id	= PS3_MATCH_ID_STOR_DISK,
534*4882a593Smuzhiyun 	.core.name	= DEVICE_NAME,
535*4882a593Smuzhiyun 	.core.owner	= THIS_MODULE,
536*4882a593Smuzhiyun 	.probe		= ps3disk_probe,
537*4882a593Smuzhiyun 	.remove		= ps3disk_remove,
538*4882a593Smuzhiyun 	.shutdown	= ps3disk_remove,
539*4882a593Smuzhiyun };
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun 
ps3disk_init(void)542*4882a593Smuzhiyun static int __init ps3disk_init(void)
543*4882a593Smuzhiyun {
544*4882a593Smuzhiyun 	int error;
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
547*4882a593Smuzhiyun 		return -ENODEV;
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun 	error = register_blkdev(0, DEVICE_NAME);
550*4882a593Smuzhiyun 	if (error <= 0) {
551*4882a593Smuzhiyun 		printk(KERN_ERR "%s:%u: register_blkdev failed %d\n", __func__,
552*4882a593Smuzhiyun 		       __LINE__, error);
553*4882a593Smuzhiyun 		return error;
554*4882a593Smuzhiyun 	}
555*4882a593Smuzhiyun 	ps3disk_major = error;
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	pr_info("%s:%u: registered block device major %d\n", __func__,
558*4882a593Smuzhiyun 		__LINE__, ps3disk_major);
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 	error = ps3_system_bus_driver_register(&ps3disk);
561*4882a593Smuzhiyun 	if (error)
562*4882a593Smuzhiyun 		unregister_blkdev(ps3disk_major, DEVICE_NAME);
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	return error;
565*4882a593Smuzhiyun }
566*4882a593Smuzhiyun 
ps3disk_exit(void)567*4882a593Smuzhiyun static void __exit ps3disk_exit(void)
568*4882a593Smuzhiyun {
569*4882a593Smuzhiyun 	ps3_system_bus_driver_unregister(&ps3disk);
570*4882a593Smuzhiyun 	unregister_blkdev(ps3disk_major, DEVICE_NAME);
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun module_init(ps3disk_init);
574*4882a593Smuzhiyun module_exit(ps3disk_exit);
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun MODULE_LICENSE("GPL");
577*4882a593Smuzhiyun MODULE_DESCRIPTION("PS3 Disk Storage Driver");
578*4882a593Smuzhiyun MODULE_AUTHOR("Sony Corporation");
579*4882a593Smuzhiyun MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_DISK);
580